这是我的source.xml:
<entries>
<entry path="/folder/abc.txt">
<a>abc</a>
<b>baz</b>
</entry>
<entry path="/other/def.txt">
<a>foo</a>
<b>bar</b>
</entry>
</entries>
我的XSLT看起来像:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:variable name="lookup">
<pair>
<key>/folder/abc.txt</key>
<value>/other/folder/abc.txt</value>
</pair>
<pair>
<key>/other/def.txt</key>
<value>/other/folder/misc/def.txt</value>
</pair>
</xsl:variable>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
因此,我可以重现我的源xml。我想要的是使用变量lookup
更新path
(其中path
应该与key
匹配以返回value
)。
最终输出为:
<entries>
<entry path="/other/folder/abc.txt">
<a>abc</a>
<b>baz</b>
</entry>
<entry path="/other/folder/misc/def.txt">
<a>foo</a>
<b>bar</b>
</entry>
</entries>
最新的要求是保持压痕的原样
我怎样才能做到这一点?
提前谢谢。
下面的XSL模板应该做到这一点。它使用EXSLT扩展函数将变量转换为节点集。(警告:如果变量中没有与路径匹配的路径,则该路径将被删除!)
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exslt="http://exslt.org/common">
<xsl:output method="xml" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:variable name="lookup">
<pair>
<key>/folder/abc.txt</key>
<value>/other/folder/abc.txt</value>
</pair>
<pair>
<key>/other/def.txt</key>
<value>/other/folder/misc/def.txt</value>
</pair>
</xsl:variable>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="entry">
<xsl:copy>
<xsl:attribute name="path">
<xsl:call-template name="replace">
<xsl:with-param name="input" select="@path"/>
</xsl:call-template>
</xsl:attribute>
<xsl:apply-templates select="*"/>
</xsl:copy>
</xsl:template>
<!-- This template looks through each pair in lookup, finds the one whose
key matches the input and returns the corresponding value. If none
match, nothing will be returned. -->
<xsl:template name="replace">
<xsl:param name="input"/>
<xsl:for-each select="exslt:node-set($lookup)/pair">
<xsl:if test="key = $input">
<xsl:value-of select="value"/>
</xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
你可以看到它在这里工作。
您可以将查找放在一个单独的文件中,并通过litte重排使其更容易:
lookup.xml:
<entries>
<entry path="/folder/abc.txt">/other/folder/abc.txt</entry>
<entry path="/other/def.txt">/other/folder/misc/def.txt</entry>
</entries>
您的xslt:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" />
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:template>
<xsl:template match="entry/@path">
<xsl:variable name="oldpath" select="." />
<xsl:attribute name="path"><xsl:value-of
select="document('lookup.xml')/entries/entry[@path = $oldpath]" /></xsl:attribute>
</xsl:template>
</xsl:stylesheet>
请注意,如果没有匹配项,则解决方案将不会保留原始值。