tags:

views:

40

answers:

3

Given the following document:

<foo>
  <object>
    <property name="value">    <!-- MATCH THIS NODE -->
      <string>alpha</string>
    </property>
    <property name="name">
      <string>$A$</string>
    </property>
  </object>
  <object>
    <property name="value">
      <string>bravo</string>
    </property>
    <property name="name">
      <string>$B$</string>
    </property>
  </object>
</foo>

and a stylesheet based on the identity transform:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>

  <!-- HAVING PROBLEMS HERE -->
  <xsl:template match="property[@name='value'][../property[@name='name']/string='$A$']">
    Replace with text!
  </xsl:template>

</xsl:stylesheet>

What predicates would I use if I want to match node indicated on the original document when I need to key off the contents of the sibling property/string element (the string $A$)?

+1  A: 

I'm not sure if this is generic enough for your needs, but this should get you close:

property[following-sibling::property[1]/string = '$A$']

This matches the property node which where the next sibling property has a child string where the text equals "$A$"

This should work if you have the same template with two property nodes, but would need to be adjusted if your XML has more property nodes.

Peter Jacoby
This works on my actual document, but there are additional <property> elements, and there are cases where the @name=name and @name=value nodes are in the opposite order.
Brian Bassett
+1  A: 

Try this:

propery[@name='value' and ../property[@name='name' and string = '$A$']]
Rubens Farias
Perfect! Thanks.
Brian Bassett
A: 

For the sake of completeness, the "top-down" XPath:

/foo/object[property[@name='name']='$A$']/property[@name='value']

Though an XML structure like the following would make much more sense:

<foo>
  <object>
    <property name="$A$">
      <string>alpha</string>
    </property>
  </object>
  <object>
    <property name="$B$">
      <string>bravo</string>
    </property>
  </object>
</foo>

because you could do

/foo/object/property[@name='$A$']
Tomalak
Unfortunately, I can't do this because the document is actually a persisted Java object (not sure what kind of persistence framework is actually being used) and the node in question may move around in the document (object elements have an id or refid attribute to link references to the same object together). I also can't restructure the document, since I don't control the format of the toolset that actually uses this document to build an installer.
Brian Bassett