Question

I'm quite new to XML transformation, so I hope someone out there can help me.

Here's the thing: I have a node with a group of child nodes. One of them needs to be transformed into an attribute, while the others should just remain as they are. My stylesheet (or rather, my template for that part) looks like this:

<xsl:template match="headerType">
  <headerType>
    <!--      <xsl:for-each select="./status">
      <xsl:attribute name="{name()}">
        <xsl:value-of select="text()"/>
      </xsl:attribute>
    </xsl:for-each>-->
    <xsl:for-each select="headerType/*">
      <xsl:choose>
        <xsl:when test="name()='status'">
          <xsl:attribute name="{name()}">
            <xsl:value-of select="text()"/>
          </xsl:attribute>
        </xsl:when>
        <xsl:otherwise>
          <xsl:copy>
            <!--<xsl:apply-templates select="@*|node()"/>-->
          </xsl:copy>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:for-each>
  </headerType>
</xsl:template>

It is supposed to convert from:

<headerType>
    <status>request</status>
    ---more child nodes here---
</headerType>

To:

<headerType status="request">
    ---the rest of the child nodes form headerType here---
</headerType>

But at the moment, it just cuts out status entirely. I'm wondering what I'm doing wrong here? Also, a recommendation for some reading about how XML transforms/stylesheets work would be appreciated. I also wonder how I can control which template run when, as I have some other template that cuts out certain nodes (tags?), which suddenly stop working for headerType and its children. So if I could know how to control the order in which the xsl:templates run, it would be nice :-)

Was it helpful?

Solution

Using name() inside your template will return 'headerType', the name of the node the template is applied too. That's why it is not working.

Why not just retrieve the node directly, like so:

<headerType>
    <xsl:attribute name="status">
        <xsl:value-of select="status"/>
    </xsl:attribute>
    <xsl:copy-of select="./*[local-name() != 'status']"/>
</headerType> 

You can filter out that status node when applying templates to the other nodes inside <headerType>

I believe you can use the 'priority' attribute on your templates to define an order, but I have never used it before (never needed too, actually). This tutorial seems to discuss the order/precedence of the templates well. Or just Google it ;)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top