Search code examples
xpathxslt-1.0siblings

XPath: how to select node that have a sibling containing text?


I have a Word XML document that is a report template. There are data indentifiers in the document in the places where real data is placed then (at report generation).

The question is: what xpath expression should I use to put table row, designated with a given data identifier (i.e. containing a cell with given text inside), into <xsl:for-each> element?

Table cells text in the document are described with elements <w:t> nested into <w:r>, then into <w:p>, <w:tc>, <w:tr> and finally into <w:tbl>. So the structure looks like this:

<w:tbl>
  <w:tr>
    <w:tc>
      <w:p>
        <w:r>
          <w:t>dataIdentifier</w:t>
        </w:r>
      </w:p>
    </w:tc>
  </w:tr>
</w:tbl>

At this time I use xsl:template with match=w:tr[contains(.//w:t,'dataIdentifier')] and Xalan to find and process such table rows, but unfortunately it finds only those <w:tr> elements that have <w:t> at first position, i.e. it doesn't work for such structures:

<w:tbl>
  <w:tr>
    ...
      <w:t>some text</w:t>
    ...
    ...
      <w:t>dataIdentifier</w:t>
    ...
  </w:tr>
</w:tbl>

What is the right XPath expression, that will check <w:tr> siblings at all positions?

P.S. due to system design I'm limited to XSLT 1.0 only =(


Solution

  • At this time I use xsl:template with match=w:tr[contains(.//w:t,'dataIdentifier')]

    Try instead:

    <xsl:template match="w:tr[.//w:t[contains(., 'dataIdentifier')]]">
    

    --
    Note: if the full path to w:t is known, it would be better to state it explicitly:

    <xsl:template match="w:tr[w:tc/w:p/w:r/w:t[contains(., 'dataIdentifier')]]">