c# - vinculado - ¿Cómo identifico los nodos duplicados en XPath 1.0 usando un XPathNavigator para evaluar?
xpath c# (2)
Voy a responder 1) , por lo que 2) no debería importar más:
Puede usar el eje preceding-sibling
en sus <Item>
para buscar elementos <Item>
anteriores con el mismo número de serie.
Pruebe esto (escrito para que solo devuelva los números de serie en lugar de los elementos; si esto no es exactamente lo que quiere, y no sabe cómo cambiar el resultado, hágamelo saber):
/Inventory/Items/Item/SerialNumber/node()[.=../../preceding-sibling::Item/SerialNumber/node()]
Para su documento de muestra, regresa
1112
Estoy tratando de identificar los números de serie duplicados del siguiente xml usando XPath 1.0 y luego evaluarlo en .Net usando un XPathNavigator
.
<?xml version="1.0" encoding="utf-16"?>
<Inventory xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Items>
<Item>
<SerialNumber>1111</SerialNumber>
</Item>
<Item>
<SerialNumber>1112</SerialNumber>
</Item>
<Item>
<SerialNumber>1112</SerialNumber>
</Item>
</Items>
</Inventory>
Intenté hacer esto evaluando esto
//Items/Item/SerialNumber
expresión en una función de contexto XSLT personalizada (implementando IXsltContextFunction
como este ejemplo de MSDN ) en .Net, pero a la función Invocar se la llama un resultado a la vez, por lo que no tengo visibilidad de los otros resultados para encontrar duplicados.
1) ¿Hay alguna forma de hacerlo con una sola expresión XPath 1.0?
O
2) ¿Hay alguna manera de pasar una matriz de elementos en una sola llamada Invoke de la clase de función de contexto XSLT personalizada? Estoy trabajando en VB.Net, pero estoy contento con cualquier ejemplo de C # que cualquiera pueda compartir.
Gracias,
Gavin
Editar
Gracias a OR Mapper y Dimitre por sus respuestas. Inicialmente acepté la respuesta de OR Mapper porque hacía lo que le pedía. Desde entonces, he aceptado la respuesta de Dimitre, ya que me gusta que proporciona una lista distinta de valores. ¡Ambas respuestas fueron muy útiles!
Uso :
/*/*/Item
[SerialNumber = following-sibling::Item/SerialNumber
and
not(SerialNumber = preceding-sibling::Item/SerialNumber)
]
Esto selecciona solo un Item
Elemento para cualquier grupo de Item
Elemento que tenga un hijo SerialNumber
con el mismo valor de cadena.
Verificación basada en XSLT :
<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="/">
<xsl:copy-of select=
"/*/*/Item
[SerialNumber = following-sibling::Item/SerialNumber
and
not(SerialNumber = preceding-sibling::Item/SerialNumber)
]"/>
</xsl:template>
</xsl:stylesheet>
Cuando se aplica esta transformación en este documento XML (basado en el proporcionado, pero hecho más interesante):
<Inventory>
<Items>
<Item>
<SerialNumber>1111</SerialNumber>
</Item>
<Item>
<SerialNumber>2222</SerialNumber>
</Item>
<Item>
<SerialNumber>2222</SerialNumber>
</Item>
<Item>
<SerialNumber>2222</SerialNumber>
</Item>
<Item>
<SerialNumber>1111</SerialNumber>
</Item>
<Item>
<SerialNumber>1111</SerialNumber>
</Item>
<Item>
<SerialNumber>3333</SerialNumber>
</Item>
</Items>
</Inventory>
la transformación evalúa la expresión XPath y copia los nodos seleccionados a la salida:
<Item>
<SerialNumber>1111</SerialNumber>
</Item>
<Item>
<SerialNumber>2222</SerialNumber>
</Item>
Finalmente, si desea obtener solo los valores duplicados de SerialNumber
, use :
/*/*/Item
[SerialNumber = following-sibling::Item/SerialNumber
and
not(SerialNumber = preceding-sibling::Item/SerialNumber)
]
/SerialNumber/text()