xslt:替换生成表中的节点值

时间:2018-08-08 07:53:08

标签: xml xslt xslt-1.0 xslt-2.0

我想匿名化xml文档中的电话号码。 数字可以出现多次,应始终用相同的值替换。

这是我的输入内容

<?xml version="1.0" encoding="UTF-8"?>
<somedata>
    <object>
        <nodeA>49123456789</nodeA>
        <nodeB>49123466666</nodeB>
    </object>
    <object>
        <nodeB>49987653333</nodeB>
    </object>
    <object>
        <nodeA>49123466666</nodeA>
    </object>
</somedata>

这是所需的输出:

<?xml version="1.0" encoding="UTF-8"?>
<somedata>
    <object>
        <nodeA>49123000001</nodeA>
        <nodeB>49123000002</nodeB>
    </object>
    <object>
        <nodeB>49987000003</nodeB>
    </object>
    <object>
        <nodeA>49123000002</nodeA>
    </object>
</somedata>

(请注意第二个和最后一个数字)

我已经可以使用此xslt进行匿名处理了:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes"/>

<xsl:template match="/" name="anonymize">

        <xsl:for-each select="distinct-values(//nodeA | //nodeB)">
        <number>
            <old><xsl:value-of select="." /></old>
            <new><xsl:value-of select="concat(substring(.,1,string-length(.)-6), format-number(position(), '000000'))"/></new>
        </number>
        </xsl:for-each>

</xsl:template>
</xsl:stylesheet>

我仍在寻找替换值的简便方法。我找到了xslt 3.0地图功能,但现在我想将其保持在xslt 1.0或2.0。

获得所需输出的最简单方法是什么? 谢谢!

1 个答案:

答案 0 :(得分:0)

尝试将XML片段存储在变量中

<xsl:variable name="phones">
    <xsl:for-each select="distinct-values(//nodeA | //nodeB)">
        <number>
            <old><xsl:value-of select="." /></old>
            <new><xsl:value-of select="concat(substring(.,1,string-length(.)-6), format-number(position(), '000000'))"/></new>
        </number>
    </xsl:for-each>
</xsl:variable>

然后,在匹配nodeAnodeB元素时,像这样获得新的数字

<xsl:value-of select="$phones/number[old=current()]/new" />

这将与身份模板一起使用,以复制其他元素。

尝试使用此XSLT

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>

<xsl:variable name="phones">
    <xsl:for-each select="distinct-values(//nodeA | //nodeB)">
        <number>
            <old><xsl:value-of select="." /></old>
            <new><xsl:value-of select="concat(substring(.,1,string-length(.)-6), format-number(position(), '000000'))"/></new>
        </number>
    </xsl:for-each>
</xsl:variable>

<xsl:template match="nodeA|nodeB">
    <xsl:copy>
        <xsl:value-of select="$phones/number[old=current()]/new" />
    </xsl:copy>
</xsl:template>

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

或者,使用键

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:key name="phones" match="number" use="old" />

<xsl:variable name="phones">
    <xsl:for-each select="distinct-values(//nodeA | //nodeB)">
        <number>
            <old><xsl:value-of select="." /></old>
            <new><xsl:value-of select="concat(substring(.,1,string-length(.)-6), format-number(position(), '000000'))"/></new>
        </number>
    </xsl:for-each>
</xsl:variable>

<xsl:template match="nodeA|nodeB">
    <xsl:copy>
        <xsl:value-of select="key('phones', ., $phones)/new" />
    </xsl:copy>
</xsl:template>

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

请注意,两种解决方案都仅是XSLT 2.0。