2012-01-06 11 views
5
<merge> 
    <text> 
     <div begin="A" end="B" /> 
     <div begin="C" end="D" /> 
     <div begin="E" end="F" /> 
     <div begin="G" end="H" /> 
    </text> 
</merge> 

Necesito un conjunto unioned de nodos de atributo, en el orden A, B, C, D, E, F, G, H, siendo este:XPath 1.0 Orden de atributos devueltos en una unión

/merge/text/div/@begin | /merge/text/div/@end 

pero solo si cada @begin viene antes de cada @end, ya que el operador de UNION está configurado para devolver nodos por orden de documento. (Sí)

necesito el nodeset estar en el mismo orden, incluso si los atributos aparecen en un orden diferente en el documento, como en este caso:

<merge> 
    <text> 
     <div end="B" begin="A" /> 
     <div begin="C" end="D" /> 
     <div end="F" begin="E" /> 
     <div begin="G" end="H" /> 
    </text> 
</merge> 

Es decir, necesito elementos para seguir orden de documento, pero los atributos en cada elemento siguen un orden determinado (ya sea especificado o alfabético por nombre de atributo).

Respuesta

6

Esto simplemente no es posible en XPath puro. En primer lugar, los atributos en XML no están ordenados. Desde el XML 1.0 Recommendation:

Tenga en cuenta que el orden de las especificaciones de atributo en una etiqueta de comienzo o etiqueta de elemento vacío no es significativo.

Un motor XPath podría estar leyéndolo y almacenándolos en el orden en que aparecen en el documento, pero en términos de la especificación, esto es solo una feliz coincidencia en la que no se puede confiar.

En segundo lugar, XPath no tiene funcionalidad de clasificación. Por lo tanto, su mejor opción es ordenar los elementos en su idioma de host (por ejemplo, XSLT o PL de propósito general) después de haberlos seleccionado.

Así es como para ordenar esos atributos de valor en XSLT:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="text"/> 
    <xsl:template match="/"> 
     <xsl:apply-templates 
      select="/merge/text/div/@*[name()='begin' or name()='end']"> 
      <xsl:sort select="."/> 
     </xsl:apply-templates> 
    </xsl:template> 
</xsl:stylesheet> 

Tenga en cuenta que también se fusionó sus dos expresiones en una sola.

Editar: la siguiente manera para comenzar la producción pares/finales en el orden del documento (como se describe en los comentarios):

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="text"/> 
    <xsl:strip-space elements="*"/> 
    <xsl:template match="div"> 
     <xsl:value-of select="concat(@begin, @end)"/> 
    </xsl:template> 
</xsl:stylesheet> 
+0

No es la respuesta que quería, pero la respuesta no obstante. Daré la pregunta a los jinetes de XSLT. – JPM

+0

@JPM - Puedo publicar una solución XSLT aquí. Un minuto. –

+0

Eso ordenará por valor de atributo, ¿verdad? Necesito el orden begin-end-begin-end -... incluso si los valores ordenarían lo contrario. (No debería haber usado ABCDEFGH en mi ejemplo.) – JPM

Cuestiones relacionadas