xml - sacar - conjunto de nodos en xpath
xpath uso (1)
Estoy escribiendo una hoja de estilo xslt para transformar un xml en otro xml.
Aquí está la versión simplificada de xml original:
<eml>
<datatable>
<physical>
<distribution id="100"/>
</physical>
</datatable>
<software>
<implementation>
<distribution id="200"/>
</implementation>
</software>
<additionalMetadata>
<describes>100</describes>
<describes>200</describes>
<describes>300</describes>
<describes>400</describes>
</additionalMetadata>
</eml>
Intento usar un Xpath para seleccionar el conjunto de nodos de "describe" que no tiene el valor que iguala el valor id de //physical/distribution
o software/implementation/distribution
. En el caso anterior, quiero obtener el conjunto de nodos:
<deseribes>300</describes>
<deseribes>400</describes>
(100 y 200 son valores de identificación de atributo de //physical/distribution
o software/implementation/distribution
).
Escribí algo como:
<xsl:with-param name="describes-list"
select="./describes[//physical/distribution/@id !=. and
//software/implementation/distribution/@id != .] "/>
Funciona en el ejemplo anterior. Sin embargo, el elemento de la tabla de datos y el software son repetibles. Entonces este xml es válido:
<eml>
<datatable>
<physical>
<distribution id="100"/>
</physical>
</datatable>
<datatable>
<physical>
<distribution id="300"/>
</physical>
</datatable>
<software>
<implementation>
<distribution id="200"/>
</implementation>
</software>
<additionalMetadata>
<describes>100</describes>
<describes>200</describes>
<describes>300</describes>
<describes>400</describes>
</additionalMetadata>
</eml>
Pero mi xslt no funciona en el ejemplo anterior :(
¿Te importaría arrojar algo de luz sobre esto? ¡Gracias de antemano!
Jing
Este es un error que a menudo se comete. Nunca use el operador "! =" De XPath cuando uno o ambos operandos son / son establecidos por nodo.
value != node-set
por definición, es verdadero si existe un nodo n en el conjunto de nodos, de modo que
value
no es igual a la string(n)
Lo que quieres es eso
value
no es igual a ningún nodo en el conjunto de nodos.
Esto se puede expresar de la siguiente manera:
value = node-set
es verdadero si existe al menos un nodo n en el conjunto de nodos, de modo que:
value = string(n)
Entonces
not(value = node-set)
es verdadero si no existe ningún nodo n en el conjunto de nodos, de modo que
value = string(n)
Por lo tanto, la siguiente expresión XPath seleccionará los nodos deseados :
/*/*/describes[not(. = ../../*/physical/distribution/@id) and not(. = ../../*/implementation/distribution/@id)]
Personalmente preferiría tener solo una comparación del nodo de contexto con la unión de los dos conjuntos de nodos:
/*/*/describes [not(. = (../../*/physical/distribution/@id | ../../*/implementation/distribution/@id ) ) ]
Tenga en cuenta que evito usar la abreviatura "//" . Por lo general, es muy costoso (ineficiente) y debe usarse solo si no conocemos la estructura del documento XML.
Y, por supuesto, las expresiones XPath anteriores deben ser evaluadas contra el siguiente documento XML (el segundo proporcionado en la pregunta):
<eml> <datatable> <physical> <distribution id="100"/> </physical> </datatable> <datatable> <physical> <distribution id="300"/> </physical> </datatable> <software> <implementation> <distribution id="200"/> </implementation> </software> <additionalMetadata> <describes>100</describes> <describes>200</describes> <describes>300</describes> <describes>400</describes> </additionalMetadata> </eml>