Is there a simple way to copy an element and its attributes while replacing just a few of the attributes?

StackOverflow https://stackoverflow.com/questions/22374514

  •  14-06-2023
  •  | 
  •  

Question

I am using XSLT to copy a file and I want to copy all the attributes of a certain node but I'd like replace some of the attributes with new ones. For example, I might have this:

<Library>
    <Book author="someone" pub-date="atime" color="black" pages="900">
    </Book>
</Library>

How could I copy this but replace pub-date and color with new values? Is there something similar to this?

<xsl:template match="/Library/Book">
    <xsl:copy>
        <xsl:attribute name="pub-date">1-1-1976</xsl:attribute>
        <xsl:attribute name="color">blue</xsl:attribute>
        <xsl:apply-templates select="*@[not pub-date or color] | node()"/>
    </xsl:copy>
</xsl:template>

But this isn't valid of course...

Was it helpful?

Solution

Another way is to rely on the fact that if the same attribute is written twice, the last one wins. So:

<xsl:template match="/Library/Book">
    <xsl:copy>
        <xsl:copy-of select="@*"/>
        <xsl:attribute name="pub-date">1-1-1976</xsl:attribute>
        <xsl:attribute name="color">blue</xsl:attribute>
        <xsl:apply-templates/>
    </xsl:copy>
</xsl:template>

(Are you quite sure you want to be using the ambiguous date format 1-1-1976?)

OTHER TIPS

I would start as usual with the identity transformation template

<xsl:template match="@* | node()">
  <xsl:copy>
    <xsl:apply-templates select="@* | node()"/>
  </xsl:copy>
</xsl:template>

and then add

<xsl:template match="Book/@pub-date">
  <xsl:attribute name="pub-date">1-1-1976</xsl:attribute>
</xsl:template>

<xsl:template match="Book/@color">
  <xsl:attribute name="color">blue</xsl:attribute>
</xsl:template>
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top