-1

i want to replace the substring of an attribute value with another value. in the sample below, i would like to take all elements with the attribute tagName = "blubb", and replace their tagValue, by finding the string "abc" in it, and replacing it with xyz. Also, the string "def" in the same attribute (if existign) should be replaced with AAA.

Sample Input:

<shop>
<items>
    <item id="1">
        <tag tagName = "Description" tagValue ="Item 1" />
        <tag tagName = "Price" tagValue = "5.00" />
        <tag tagName = "Currency" tagValue = "USD" />
        <tag tagName = "blubb" tagValue = "abc,def,ghi,jkl" />
    </item>
    <item id="2">
        <tag tagName = "Description" tagValue ="Item 2" />
        <tag tagName = "Price" tagValue = "5.00" />
        <tag tagName = "Currency" tagValue = "EUR" />
        <tag tagName = "blubb" tagValue = "def,ghi,jkl" />
    </item>
    <item id="2">
        <tag tagName = "Description" tagValue ="Item 2" />
        <tag tagName = "Price" tagValue = "5.00" />
        <tag tagName = "Currency" tagValue = "EUR" />
        <tag tagName = "blubb" tagValue = "abc,def,jkl" />
    </item>
</items>
</shop>

Expected Output (abc replaced with xyz and def replaced with AAA)

<shop>
<items>
    <item id="1">
        <tag tagName = "Description" tagValue ="Item 1" />
        <tag tagName = "Price" tagValue = "5.00" />
        <tag tagName = "Currency" tagValue = "USD" />
        <tag tagName = "blubb" tagValue = "xyz,AAA,ghi,jkl" />
    </item>
    <item id="2">
        <tag tagName = "Description" tagValue ="Item 2" />
        <tag tagName = "Price" tagValue = "5.00" />
        <tag tagName = "Currency" tagValue = "EUR" />
        <tag tagName = "blubb" tagValue = "AAA,ghi,jkl" />
    </item>
    <item id="2">
        <tag tagName = "Description" tagValue ="Item 2" />
        <tag tagName = "Price" tagValue = "5.00" />
        <tag tagName = "Currency" tagValue = "EUR" />
        <tag tagName = "blubb" tagValue = "xyz,AAA,jkl" />
    </item>
</items>
</shop>

Is that possible with xslt?

Thanks!

UPDATE - i tried adapting my xsl with the replace function- i had a copy-of before and adapted it to a copy as in the sample below, however i dont get any data now anymore, so i tried making it work with copy-of again When i do that, it doesn't replace anything. I suppose that is because i have twiche xsl:template in it, is it?

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="no" indent="yes"/>
<xsl:template match="items">
    <xsl:copy-of select="item[@type='DEVICE']/tag[@tagName='Currency' and starts-with(@tagValue,'EUR')]/.."/>
</xsl:template>
<xsl:template match="item/tag[@tagName='blubb']">
    <xsl:param name="tagValue" />
    <xsl:variable name="tagValue" select="replace($tagValue,'abc','xyz')"/>
    <xsl:variable name="tagValue" select="replace($tagValue,'def','AAA')"/>
</xsl:template>
</xsl:stylesheet>
Eva
  • 1
  • 3
  • 2
    The answer is "yes", it is possible with xslt. But how it is done depends on the version of XSLT you are using. Are you able to use XSLT 2.0, as this has the `replace` function available? Also, is your expected output correct, as in the second item, the "def" value seems to have been replaced with "xyz" rather than '"AAA", and in the third item, "def" has not been replaced at all. Thanks! – Tim C Aug 21 '19 at 12:27
  • Additionally, because StackOverflow is not a code-writing service, please share your attempted XSLT code so we can help on specifics to your problem. – Parfait Aug 21 '19 at 13:44
  • Thanks for pointing out the typo in the desired result, i changed that :) And i can use 2.0, so i'm trying the replace function – Eva Aug 21 '19 at 15:22
  • While using just `replace()` could work, there might be cases where it won't. For example, if you have `abcoulomb` in your attribute value does it need to become `xyzoulomb` or should it remain unchanged? – Daniel Haley Aug 21 '19 at 17:04

3 Answers3

0

You can refer to this article: XSLT string replace

To resume:

  • For XSLT 2.0:

    By using the replace function <xsl:variable name="text" select="replace($text,'word_to_be_replaced','word_to_replace')"/>

  • For XSLT 1.0:

    1. Test if the String to replace exists (<xsl:when test="contains($text, $word_to_be_replaced)">)
    2. If so, output the substring before (<xsl:value-of select="substring-before($text,$word_to_be_replaced)" />), the word to replace, the substring after ((<xsl:value-of select="substring-after($text,$word_to_be_replaced)" />)).
Nechadil
  • 341
  • 3
  • 6
0

Beware of using a simple:

replace($value,'abc','XYZ')

You might get false positives when a token only contains the substring abc - e.g. abcdef or deabcef or defabc.

To make sure you only replace a whole token abc, use:

replace($value, '(^|,)abc(,|$)', '$1XYZ$2')

Demo: https://xsltfiddle.liberty-development.net/ej9EGdo

michael.hor257k
  • 113,275
  • 6
  • 33
  • 51
0

You Can try This -

    <?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="xs"
    version="2.0">
    <xsl:output method="xml" omit-xml-declaration="no"/>
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="tag[@tagName[.='blubb']]/@tagValue">
                <xsl:attribute name="tagValue">
                    <xsl:analyze-string select="." regex="(abc)|(def)">
                        <xsl:matching-substring>
                            <xsl:choose>
                                <xsl:when test="regex-group(1)">
                                    <xsl:text>xyz</xsl:text>
                                </xsl:when>
                                <xsl:when test="regex-group(2)">
                                    <xsl:text>AAA</xsl:text>
                                </xsl:when>
                            </xsl:choose>
                        </xsl:matching-substring>
                        <xsl:non-matching-substring>
                            <xsl:value-of select="."/>
                        </xsl:non-matching-substring>
                    </xsl:analyze-string>
                </xsl:attribute>
    </xsl:template>
</xsl:stylesheet>

Use this analyze-string

Sam
  • 841
  • 1
  • 5
  • 15
  • I gotta admit, i have to find a quiet hour to actually process why and how that works (and how to reapply my currency starts with EUR filter), but it does - thank you very much! – Eva Aug 22 '19 at 09:28