[ACCEPTED]-Working With Nested XPath Predicates ... Refined-xpath

Accepted answer
Score: 10

Generally you should avoid using // where 10 you can. I'd consider rephrasing:

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

In the 9 expression provided, your nested predicate 8 is actually checking for

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

of which there 7 are none.

I hope this helps!

EDIT: Since the 6 question has been updated here is an updated 5 response: You added "It seems the @objectId 4 in the nested predicate does not refer to 3 the objectId attribute of the object node." You're 2 absolutely right! So let's fix it!!

//object[../properties[not(@refPropertyId)]/@refObjectId=@objectId]

This 1 should be closer to what you're after!

Score: 0

Try this:

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

0

Score: 0

This should work:

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

I am not sure how your 7 xml is. However, if it is in the following 6 format:

<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>

Then you should use the following 5 xpath to get only objects 1111 and 7111. The 4 result should not include 4111 because the 3 properties where refObjectId = 4111 does 2 not immediately follow the object whose 1 objectId=4111.

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

Assuming that all <properties> nodes that belong to 6 a given <object> actually follow that object (your input 5 seems to imply that), you could do:

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

This 4 should perform pretty well.

If you happen 3 to be in XSLT, things get a lot simpler:

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

and 2

<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>

In the XSLT case, the order of object and 1 proerties nodes becomes irrelevant.

More Related questions