这是我的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。我想要的是使用变量path
更新lookup
(其中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>
最新的要求是完全保留缩进。
我怎样才能做到这一点?
提前致谢。
答案 0 :(得分:2)
以下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>
您可以看到它正常工作here。
答案 1 :(得分:1)
您可以将查找放在单独的文件中,并通过重新排列来简化:
<强> 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>
请注意,如果没有匹配项,解决方案将不会保留原始值。