1

I wanted to replace wildcards in a control XML-file from a third-party software.

Unfortunately these wildcards also used as attribute values in this XML-file.

I will give you an example:

<control>
  <some-tag id="$wildcard1$" version="3.14">
    <another-tag id="second_level">stackoverflow rocks!</another-tag>
  </some-tag>
  <some-tag id="foo" version="$wildcard2$"/>
  <some-tag id="bar" version="145.31.1"/>
</control>

I tried to write a generic transformation with parameters to replace the wildcards in the attribute values.

My biggest problem was, that i don't know the attribute name. So i need to match every attribute in the XML file. That is easy but how i match every attribute with a specific value (e.g. $wildcard$) ?

1 Answer 1

1

The answer to this question was quite easier than I thought it would be.

<xsl:template match="@*[. = $wildcard]">
    <xsl:attribute name="{name(.)}">
        <xsl:value-of select="$wildcard_value"/>
    </xsl:attribute>
</xsl:template>

I hope it helps someone.

P.S: Here is my full XSL-Transformation to replace wildcards in attributes values:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:fn="http://www.w3.org/2005/xpath-functions">
    <xsl:param name="wildcard" required="yes" />
    <xsl:param name="wildcard_value" required="yes" />
    <xsl:output method="xml" version="1.0" encoding="UTF-8"
        indent="yes" />
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()" />
        </xsl:copy>
    </xsl:template>
    <xsl:template match="@*[. = $wildcard]">
        <xsl:attribute name="{name(.)}">
            <xsl:value-of select="$wildcard_value" />
        </xsl:attribute>
    </xsl:template>
</xsl:stylesheet>
Sign up to request clarification or add additional context in comments.

2 Comments

Note that match="*/@*[. = $wildacard]" can be shortened to match="@*[. = $wildacard]". And if you really use XSLT version 3.0 then instead of the first template you have you can simply declare <xsl:mode on-no-match="shallow-copy"/>. I also notice that your declared param name is name="wildcard", yet your code references $wildacard.
<xsl:mode on-no-match="shallow-copy"/> only works with the enterprise version of saxon. So i decided to tag the stylesheet as version 2.0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.