2009-06-08 70 views
6
refinados

Todos los grandes respuestas! Pero la cuestión merece refinamiento ...Trabajar con anidada XPath predicados ...

Tengo el siguiente código XML muestra ...

<objects> 
    <object objectId="1123" ... /> 
    <properties refObjectId="1123" ... /> 
    <properties refObjectId="1123" refPropertyId="2311" ... /> 
    <properties refObjectId="1123" refPropertyId="4611" ... /> 
    <object objectId="2123" ... /> 
    <properties refObjectId="2123" refPropertyId="4311" ... /> 
    <properties refObjectId="2123" refPropertyId="8611" ... /> 
    .... 
</objects> 

... y la siguiente consulta XPath ...

//object[//properties[@[email protected] and not(@refPropertyId)]] 

pensé esta consulta devolvería todos los nodos object donde hay un nodo properties que tiene un atributo refObjectId que es igual al atributo objectId del nodo objecty no tiene atributos 'refPropertyId' bute ... es decir, solo el objeto 1123, no el objeto 2123 ... pero no es así. Parece que el @objectId en el predicado anidado no hace referencia al atributo objectId del nodo object.

¿Alguna idea? Sé que la estructura XML no está anidada como era de esperar, pero hay razones para esta estructura.

+0

¿Tiene varios nodos de objeto dentro del nodo de objetos donde las propiedades de un objeto particular se encuentran justo debajo de ese objeto? –

Respuesta

7

En general, usted debe evitar el uso // donde se puede. Me gustaría considerar reformular:

//object[../properties/@[email protected]] 

En la expresión proporcionada, el predicado anidado es en realidad la comprobación de

//properties/@refObjectId=//properties/@objectId 

de los cuales no hay ninguno.

Espero que esto ayude!

EDITAR: Dado que la pregunta se ha actualizado aquí es una respuesta actualizada: Agregó "Parece que @objectId en el predicado anidado no se refiere al atributo objectId del nodo de objeto." ¡Estás absolutamente en lo correcto! ¡¡Entonces arreglemoslo !!

//object[../properties[not(@refPropertyId)]/@[email protected]] 

Esto debería estar más cerca de lo que está buscando!

+1

Nice XPath, Jweede. –

0

Prueba esto:

//objects[object/@objectId = properties/@refObjectId]/object 
0

esto debería funcionar:

//objects/object[@objectId = ../properties/@refObjectId] 

No estoy seguro de cómo el código XML es. Sin embargo, si se encuentra en el siguiente formato:

<objects> 
    <object objectId="1111" /> 
    <properties refObjectId="1111" /> 
    <object objectId="2111" /> 
    <properties refObjectId="3111" /> 
    <object objectId="4111" /> 
    <properties refObjectId="5111" /> 
    <object objectId="6111" /> 
    <properties refObjectId="4111" /> 
    <object objectId="7111" /> 
    <properties refObjectId="7111" /> 
</objects> 

, entonces debería usar el siguiente XPath para obtener objetos sólo 1111 y 7111. El resultado no debe incluir 4111 debido a que las propiedades donde refObjectId = 4111 no se sigue de inmediato la objeto cuyo objectId = 4111.

//objects/properties[@refObjectId = preceding::object[1]/@objectId]/preceding::object[1] 
0

Suponiendo que todos los <properties> nodos que pertenecen a un determinado <object> realidad siguen ese objeto (su entrada parece implicar que), que podría hacer:

/objects/properties[ 
    @refObjectId = preceding-sibling::object[1]/@objectId 
    and 
    not(@refPropertyId) 
]/preceding-sibling::object[1] 

Esto debe llevar a cabo bastante bien.

Si usted sucede estar en XSLT, las cosas se ponen mucho más simple:

<xsl:key name="kPropertiesByObjectId" match="properties" use="@refObjectId" /> 

y

<xsl:template match="object"> 
    <!-- This tests for an empty node-set. Non-empty node sets can only happen 
     for objects with at least one <properties> node without @refPropertyId --> 
    <xsl:if test="key('kPropertiesByObjectId', @objectId)[not(@refPropertyId)]"> 
    <xsl:copy-of select="." /> 
    </xsl:if> 
</xsl:template> 

En el caso de XSLT, el orden de los objetos y proerties nodos se convierte en irrelevante.