xpath: concatenate sibling node text

Given the sample XML data:

<root>
  <a>
    <id>1</id>
    <status>on</status>
    <level>4</level>
    <otherData>asdfasdfsdfvasdF</otherData>
    <b>
        <name>A1</name>
    </b>
  </a>
  <a>
    <id>2</id>
    <status>on</status>
    <level>8</level>
    <otherData>asdfasdfsdfvasdF</otherData>
    <b>
        <name>TEST</name>
    </b>
  </a>
  <a>
    <id>3</id>
    <status>off</status>
    <level>2</level>
    <otherData>asdfasdfsdfvasdF</otherData>
    <b>
        <name>A1</name>
    </b>
  </a>
</root>

I'd like to write an XPath expression that will evaluate to:

1 on
3 off

That is, I'd like to extract the text of the id node and concatenate it with the status node. There is an additional condition: I only want to do this for cases where the name is "A1". The XPath expression to just get the id is this:

//name[text()="A1"]/../../id/text()

And here's an attempt to concatenate id with it's sibling status, which does not work.

//name[text()="A1"]/../../concat(id/text() , status/text())

Is what I'm trying to do even possible? And if so, what would be the correct XPath expression?


To clarify: I'm not doing any transformations with this expression, I'm just plugging it into an XPath expression evaluator (such as in Notepad++ or JEdit - via plugins) to help debug subtle data errors in very large XML files. In this example, certain combinations of id and status might not be correct if the b child element has name="A1", so I am trying to find them all with one simple expression rather than scrolling through the file by hand.

Upvotes: 0

Views: 3514

Answers (2)

mzjn
mzjn

Reputation: 50947

XPath 2.0:

for $n in /root/a[b/name[.='A1']] return concat($n/id, ' ' , $n/status) 

Result:

1 on
3 off

Tested in Oxygen XML Editor, a very good tool IMHO.

Upvotes: 2

Timur Sadykov
Timur Sadykov

Reputation: 11377

Try this. You just need to add desired formatting )

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
>
  <xsl:template match="root">
    <xsl:apply-templates select="//name[text()='A1']"></xsl:apply-templates>
  </xsl:template>
  <xsl:template match="name[text()='A1']">
      <xsl:value-of select="../../id"/>
      <xsl:text> </xsl:text>
    <xsl:value-of select="../../status"/>
  </xsl:template>
</xsl:stylesheet>

Upvotes: 0

Related Questions