2010-12-22 20 views
6

Quiero transformar un documento XML en HTML. Algunos elementos XML tienen enlaces a otros documentos como:cómo generar una cadena única

<link href="1.html"> 

En la salida HTML, quiero llegar:

<a href="1.html&no_cache={unique_id}"> 

¿Cómo puedo generar este único bastante grande identificación?

+0

[generate-id()] (http://www.w3schools.com/XSL/func_generateid.asp). – khachik

+1

no encaja en mi caso. generate-id() no genera identificadores únicos si intento procesar este xml varias veces. Quiero tener una identificación única cada vez – Nawa

+0

Buena pregunta, +1. Vea mi respuesta para una solución XSLT completa y corta. :) –

Respuesta

5

Para empezar, supongo que debido a alguna razón desconocida no se puede utilizar la dirección URL absoluta en el link como el UID es necesario - esta es la solución más simple y más natural.

En caso de que mi suposición es correcta, entonces:

Esta es una tarea fácil para XSLT.

Como OP quiere que los identificadores generados sean los mismos cuando la transformación se realiza varias veces, no es apropiado utilizar la función generate-id().

Esta es una manera sencilla de producir los identificadores estables:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 
<xsl:strip-space elements="*"/> 

<xsl:template match="node()|@*"> 
    <xsl:copy> 
     <xsl:apply-templates select="node()|@*"/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="link[@href]"> 
    <xsl:variable name="vUid"> 
    <xsl:number level="any" count="link[@href]"/> 
    </xsl:variable> 
    <a href="{@href}&amp;no_cache={{{$vUid}}}"/> 
</xsl:template> 
</xsl:stylesheet> 

cuando se aplica esta transformación en el siguiente documento XML (sin importar cuántas veces):

<t> 
<link href="1.html"/> 
<a> 
    <link href="2.html"/> 
    <b> 
    <link href="3.html"/> 
    <c> 
    <link href="4.html"/> 
    </c> 
    <link href="5.html"/> 
    </b> 
    <link href="6.html"/> 
    <d> 
    <link href="7.html"/> 
    </d> 
</a> 
<link href="8.html"/> 
<e> 
    <link href="9.html"/> 
</e> 
<link href="10.html"/> 
</t> 

el resultado deseado, el mismo y correcto se produce cada vez:

<t> 
    <a href="1.html&amp;no_cache={1}"/> 
    <a> 
     <a href="2.html&amp;no_cache={2}"/> 
     <b> 
     <a href="3.html&amp;no_cache={3}"/> 
     <c> 
      <a href="4.html&amp;no_cache={4}"/> 
     </c> 
     <a href="5.html&amp;no_cache={5}"/> 
     </b> 
     <a href="6.html&amp;no_cache={6}"/> 
     <d> 
     <a href="7.html&amp;no_cache={7}"/> 
     </d> 
    </a> 
    <a href="8.html&amp;no_cache={8}"/> 
    <e> 
     <a href="9.html&amp;no_cache={9}"/> 
    </e> 
    <a href="10.html&amp;no_cache={10}"/> 
</t> 

Nota: El uso de <xsl:number> para producir la identificación.

Si el mismo enlace puede ocurrir varias veces en el documento y necesitamos todas las ocurrencias de utilizar el mismo ID, aquí está la solución para este problema:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 
<xsl:strip-space elements="*"/> 

<xsl:key name="kHrefByVal" match="link/@href" use="."/> 

<xsl:variable name="vUniqHrefs" select= 
    "//link/@href 
     [generate-id() 
     = 
     generate-id(key('kHrefByVal',.)[1]) 
     ] 
    "/> 


<xsl:template match="node()|@*"> 
    <xsl:copy> 
     <xsl:apply-templates select="node()|@*"/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="link[@href]"> 
    <xsl:variable name="vthisHref" select="@href"/> 

    <xsl:variable name="vUid"> 
    <xsl:for-each select="$vUniqHrefs"> 
    <xsl:if test=". = $vthisHref"> 
    <xsl:value-of select="position()"/> 
    </xsl:if> 
    </xsl:for-each> 
    </xsl:variable> 
    <a href="{@href}&amp;no_cache={{{$vUid}}}"/> 
</xsl:template> 
</xsl:stylesheet> 

cuando se aplica en esta transformación el siguiente documento XML:

<t> 
<link href="1.html"/> 
<a> 
    <link href="2.html"/> 
    <b> 
    <link href="1.html"/> 
    <c> 
    <link href="3.html"/> 
    </c> 
    <link href="2.html"/> 
    </b> 
    <link href="1.html"/> 
    <d> 
    <link href="3.html"/> 
    </d> 
</a> 
<link href="4.html"/> 
<e> 
    <link href="2.html"/> 
</e> 
<link href="4.html"/> 
</t> 

el resultado deseado, se produce correcta:

<t> 
    <a href="1.html&amp;no_cache={1}"/> 
    <a> 
     <a href="2.html&amp;no_cache={2}"/> 
     <b> 
     <a href="1.html&amp;no_cache={1}"/> 
     <c> 
      <a href="3.html&amp;no_cache={3}"/> 
     </c> 
     <a href="2.html&amp;no_cache={2}"/> 
     </b> 
     <a href="1.html&amp;no_cache={1}"/> 
     <d> 
     <a href="3.html&amp;no_cache={3}"/> 
     </d> 
    </a> 
    <a href="4.html&amp;no_cache={4}"/> 
    <e> 
     <a href="2.html&amp;no_cache={2}"/> 
    </e> 
    <a href="4.html&amp;no_cache={4}"/> 
</t> 
+0

+1 Buena respuesta. En el segundo podría usar la tecla '' para un mejor rendimiento. –

3

try generate-id().

<xsl:value-of select="generate-id(.)"/> 

aquí es una explicación adicional: http://www.w3schools.com/XSL/func_generateid.asp

+0

generate-id (.) No genera identificadores únicos si intento procesar este xml varias veces. Deseo tener una ID única cada vez – Nawa

+0

@Nawa: la función 'generate-id()' garantiza un identificador único para cada nodo en la fuente de entrada ** durante la misma transformación **. Si quiere un identificador único para todos los tiempos, entonces necesita implementar algún algoritmo como MD5 –

+0

hi nawa. debe generar nuevos identificadores cada vez que llame a la transformación. pero no existe unfaik estándar para la generación de estas identificaciones. w3c acaba de decir que esta identificación es única en todos los nodos de la transformación actual. su mejor opción para los identificadores verdaderamente únicos sería usar algo como llamar a los métodos .net con su transformación xsl y devolver Guid.NewGuid() desde el ensamblado .net. o alternativamente simplemente transforme y a # UNIQUEID # (texto estático) y reemplace cada aparición de # UNIQUEID # después con un idioma de su elección con un identificador único. –

0

XSLT es un lenguajes funcionales lo que significa para una entrada dada lo hará siempre producto la misma salida, por lo que, por definición, un método GUID o cualquier otro generador aleatorio no lo haría ser parte de la especificación de diseño. Su mejor apuesta si está vinculado al cliente es utilizar un método relacionado con el tiempo como parte de una semilla pseudoaleatoria para generar ID, sin embargo, como su objetivo parece ser fuerte, debe abandonar esto y concentrarse en aplicar el correcto encabezados anti-caché de los recursos que intenta proteger.

2

que no es posible con XSLT pura, pero algunas opciones alternativas podrían ser:

  1. Añadir un espacio de nombres de extensión para que pueda llamar a código no XSLT: <a href="1.html&no_cache={myns:unique_id()}">. Esto le dará el resultado que busca, pero depende del soporte del marco que está utilizando para realizar la transformación.
  2. Utilice JavaScript para agregar la ID única a los enlaces en el cliente. Solo funciona si su cliente tiene JavaScript habilitado, pero puede ser un compromiso aceptable si sabe que este será el caso.
  3. Establezca los encabezados HTTP en sus páginas para evitar el almacenamiento en caché. Probablemente sea la mejor opción desde un punto de vista semántico, y no correrá el riesgo de que los motores de búsqueda rastreen repetidamente su página con cada ID único.
+0

Buenas sugerencias, aunque "No es posible con XSLT puro" no es cierto. – LarsH

Cuestiones relacionadas