Change value in specific attribute using XSLT

I am trying to write my first XSLT. It needs to find all elements bind

where the attribute ref

starts with "$ .root" and then ".newRoot" is inserted. I was able to match a specific attribute, but I don't understand how I can get it to print the updated attribute value.

XML input example:

<?xml version="1.0" encoding="utf-8" ?>
<top>
    <products>
        <product>
            <bind ref="$.root.other0"/>
        </product>
        <product>
            <bind ref="$.other1"/>
        </product>
        <product>
            <bind ref="$.other2"/>
        </product>
        <product>
            <bind ref="$.root.other3"/>
        </product>
    </products>
</top>

      

My XSL so far:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

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

    <xsl:template match="bind[starts-with(@ref,'$.root')]/@ref">
        <xsl:attribute name="ref">$.newRoot<xsl:value-of select="bind/@ref" /></xsl:attribute>
    </xsl:template>
</xsl:stylesheet>

      

XML I would like to create from input:

<?xml version="1.0" encoding="utf-8" ?>
<top>
    <products>
        <product>
            <bind ref="$.newRoot.root.other0"/>
        </product>
        <product>
            <bind ref="$.other1"/>
        </product>
        <product>
            <bind ref="$.other2"/>
        </product>
        <product>
            <bind ref="$.newRoot.root.other3"/>
        </product>
    </products>
</top>

      

+3


source to share


1 answer


Instead:

<xsl:template match="bind[starts-with(@ref,'$.root')]/@ref">
    <xsl:attribute name="ref">$.newRoot<xsl:value-of select="bind/@ref" /></xsl:attribute>
</xsl:template>

      

try:

<xsl:template match="bind[starts-with(@ref,'$.root')]/@ref">
    <xsl:attribute name="ref">$.newRoot.root<xsl:value-of select="substring-after(., '$.root')" /></xsl:attribute>
</xsl:template>

      



or (the same in more convenient syntax):

<xsl:template match="bind/@ref[starts-with(., '$.root')]">
    <xsl:attribute name="ref">
        <xsl:text>$.newRoot.root</xsl:text>
        <xsl:value-of select="substring-after(., '$.root')" />
    </xsl:attribute>
</xsl:template>

      


Note the usage .

to refer to the current node. In your version, the command <xsl:value-of select="bind/@ref" />

doesn't select anything because the attribute is ref

already the current node - and it has no children.

+6


source







All Articles