0
votes

I'd like to select the value of a certain attribute from all tags where another attribute matches a condition.

For example, if my XML document is:

<?xml version="1.0"?>
<doc>
  <mytag txt="alpha" foo="a"></mytag>
  <mytag txt="beta"  foo="b"></mytag>
</doc>

I'd like to use a XSLT file like this:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:template match="/">
    <xsl:for-each select="doc/mytag">
      |<xsl:value-of select="@txt[@foo='a']"/>|
    </xsl:for-each>
  </xsl:template>
</xsl:stylesheet>

To get output like this:

|alpha|

Instead, nothing is selected.

If I wrap the [xsl:value-of] tag with a [xsl:if test="@foo='a'"] tag, it will work:

...
<xsl:for-each select="doc/mytag">
  <xsl:if test="@foo='a'">
    |<xsl:value-of select="@txt"/>|
  </xsl:if>
</xsl:for-each>

But I'd like to avoid that if possible, simply to save on space since I have ~20 separate tags I'd like to extract.

I'm guessing this is an xpath problem, but after fairly lengthy searching, I haven't found a solution. Any help is appreciated.

2
Change @txt[@foo='a'] to [@foo='a']/@txtSomeDude
I tried that, but it didn't work - no output at all, not even the bar (|) characters.user6654769

2 Answers

0
votes

The syntax you are looking for is this....

|<xsl:value-of select="@txt[../@foo='a']"/>|

However, this would outout || in the case where @foo wasn't equal to a. So, what you could do is more the condition to the xsl:for-each instead

<xsl:for-each select="doc/mytag[@foo='a']">
  |<xsl:value-of select="@txt"/>|
</xsl:for-each>
0
votes

Seems like this would be better done using a template:

<transform xmlns="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <output method="text"/>
    <template match="child::doc/child::mytag[count(attribute::foo) = 1 and (string(attribute::foo) = 'a' or string(attribute::foo) = 'c')]">
        <value-of select="concat('|', string(attribute::txt), '|')"/>
    </template>
</transform>