0
votes

I'm new to XSLT and can't figure out how to copy an attribute from a child tag to a new tag. I'm pretty sure it's a stupid beginner's mistake.

The input file is:


    <?xml version="1.0" encoding="UTF-8"?>
    <navMap>
    <navPoint>
      <navLabel>
        <text>Chapter 1</text>
      </navLabel>
      <content src="Text/chapter01.html"/>
    </navPoint>
    </navMap>

The XSLT that I have so far is:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
  <html>
  <body>
       <xsl:for-each select="navMap/navPoint">
            <h1><span><xsl:value-of select="./content/@src" /></span><xsl:value-of select="./navLabel/text" /></h1>
       </xsl:for-each>
  </body>
  </html>
</xsl:template>
</xsl:stylesheet>

This'll generate:

<h1><span>Text/chapter01.html</span>Chapter 1</h1>

however, I need:

<h1 href="Text/chapter01.html">Chapter 1</h1>

How do I add a new href attribute to the h1 tag and copy the value of the src attribute of the content tag?

I tried:

<h1 href="<xsl:value-of select="./content/@src" />"><xsl:value-of select="./navLabel/text" /></h1>

but that generated a syntax error.

1

1 Answers

3
votes

The preferred way is usually to use Attribute Value Templates.

<xsl:template match="/">
  <html>
  <body>
       <xsl:for-each select="navMap/navPoint">
            <h1 href="{content/@src}">
                <xsl:value-of select="navLabel/text" />
            </h1>
       </xsl:for-each>
  </body>
  </html>
</xsl:template>

The curly braces indicate an expression to be evaluated, rather than output literally.

You can also use xsl:attribute to create an attribute

<xsl:template match="/">
  <html>
  <body>
       <xsl:for-each select="navMap/navPoint">
            <h1>
                <xsl:attribute name="href">
                    <xsl:value-of select="content/@src" />
                </xsl:attribute>
                <xsl:value-of select="navLabel/text" />
            </h1>
       </xsl:for-each>
  </body>
  </html>
</xsl:template>

But as you can see this is slightly more long-winded. You could use this though if you wanted it to be conditional (i.e. only to be added in certain circumstances), for example, or if the expression was much too complicated to fit in an Attribute Value Template.