1

I want to test if the name of the attribute contains 'description' (doesn't matter whether it is description1, 2 or 3, as long as the name has description in it) and then use this in for-each cycle. If not, I don't want to show the element. So I have an XML structure like the following:

<item>
 <name>Test xslt</name>
 <code>XSLT</code>
 <description>
  <description1>1x stay</description1>
  <description2>1x breakfast</description2>
  <description3>1x diner</description3>
  <description4>1x free late check-out</description1>
  <address>New York 1234AZ</address>
 </description>
</item>

And then my XSLT would be:

<xsl:for-each select="description">
   <xsl:if test=""> (test here if name cointains description)
     <p><xsl:value-of select="." /></p>
   </xsl:if>
</xsl:for-each>

Now it also shows the element in the array. Does anyone know how to test if the name of element contains specific text and then only show these? Thanks in advance!

Edit:

Fixed the edit already.

1 Answers1

2

This will do without the extra xsl:if

  <xsl:for-each select="//*[contains(local-name(),'description')]">
    <p><xsl:value-of select="." /></p>
  </xsl:for-each>

Like @michael.hor257k in his comment suggests: If you don't use namespace-prefixes and your "description*"-elements always starts with "description" you could make it perform better by using:

  <xsl:for-each select="//*[starts-with(name(),'description')]">
    <p><xsl:value-of select="." /></p>
  </xsl:for-each>

See this answer for explanation difference name() and local-name()

If your context in xslt is the item-element you could also make it work faster like this:

  <xsl:for-each select="descendant::*[starts-with(name(),'description')]">
    <p><xsl:value-of select="." /></p>
  </xsl:for-each>

This site gives you some more help on how xslt works and how the context is changing, i.e. by using xsl:apply-templates or xsl:for-each

Siebe Jongebloed
  • 3,906
  • 2
  • 14
  • 19
  • 1
    See also [this SO question and answer](https://stackoverflow.com/questions/585261/is-there-an-xslt-name-of-element) which has some additional details. – MyICQ May 26 '21 at 14:51
  • Nice, this works perfectly, thanks! I noticed that it doesn't work without the //*[]. Could you tell me what it does? – Sybrentjuhh May 26 '21 at 16:55
  • // = every where in the xml * = any element [] = the XPath predicate(a kind of filter) If you only want it be used inside an item, you could use //item//*[contains(local-name(),'description')] Meaning any element that is a descendant of item with element-name that contains description – Siebe Jongebloed May 26 '21 at 17:03
  • 1
    @Sybrentjuhh You probably want to use ``. I say "probably" because you did not make it clear what is the context of this instruction. In general, the more specific your path is, the less processing it requires. A path using the child axis is more efficient than one using the descendant axis. – michael.hor257k May 26 '21 at 17:27
  • @SiebeJongebloed I've actually encountered a new problem now which I didn't antipicate beforehand.. I've edited my question accordingly, would be great if you could help me with this problem aswell.. :-) – Sybrentjuhh May 26 '21 at 17:50
  • If you don't solve the new problem, just post a new question. – Siebe Jongebloed May 26 '21 at 17:59