我想用多个元素替换XML(大)中的元素,如下所示:
原始XML:
<root>
<cr>
<id>1</id>
<release>A</release>
</cr>
<cr>
<id>2</id>
<release>B</release>
</cr>
</root>
我希望输出为:
<root>
<cr>
<id>1</id>
<release>Aa</release>
<release>Ab</release>
<release>Ad</release>
</cr>
<cr>
<id>2</id>
<release>Bd</release>
<release>Be</release>
</cr>
</root>
原则是,每当//释放[text()=&#39; A&#39;]时,只要有//释放[text()=&#39; B&#39;],用上面的两个替换元素等。如果发布文本()是&#34; C&#34;或&#34; D&#34;或其他值,它们保持相同的值。
我的尝试:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<!-- identity transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="//cr/release/text()">
<xsl:if test=".='A'">
<xsl:value-of select="Aa"/>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
它适用于一个 - &gt;一个替代,但如何做多个?非常感谢,
答案 0 :(得分:2)
以这种方式尝试:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<!-- identity transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="release[.='A']">
<release>Aa</release>
<release>Ab</release>
<release>Ad</release>
</xsl:template>
<xsl:template match="release[.='B']">
<release>Bd</release>
<release>Be</release>
</xsl:template>
</xsl:stylesheet>
测试输入
<root>
<cr>
<id>1</id>
<release>A</release>
</cr>
<cr>
<id>2</id>
<release>B</release>
</cr>
<cr>
<id>3</id>
<release>C</release>
</cr>
</root>
<强>结果强>
<?xml version="1.0" encoding="UTF-8"?>
<root>
<cr>
<id>1</id>
<release>Aa</release>
<release>Ab</release>
<release>Ad</release>
</cr>
<cr>
<id>2</id>
<release>Bd</release>
<release>Be</release>
</cr>
<cr>
<id>3</id>
<release>C</release>
</cr>
</root>
答案 1 :(得分:2)
这是一个完全通用且简短的XSLT 1.0解决方案。它使用映射 xml文件,指定每个所需版本的替换:
(请在本答案的最后找到用XSLT 2.0编写的最终通用和简短的解决方案。)
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:variable name="vMap" select="document('mapping.xml')/*/*"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="release[. = document('mapping.xml')/*/release/@old]">
<xsl:copy-of select="$vMap[@old = current()]/*"/>
</xsl:template>
</xsl:stylesheet>
如果文件mapping.xml
与转换(.xsl文件)位于同一目录中,则为:
<map>
<release old="A">
<release>Aa</release>
<release>Ab</release>
<release>Ad</release>
</release>
<release old="B">
<release>Ba</release>
<release>Bb</release>
<release>Bd</release>
</release>
</map>
然后在此XML文档上应用转换时:
<root>
<cr>
<id>1</id>
<release>A</release>
</cr>
<cr>
<id>2</id>
<release>B</release>
</cr>
<cr>
<id>3</id>
<release>C</release>
</cr>
<cr>
<id>4</id>
<release>D</release>
</cr>
</root>
产生了想要的正确结果:
<root>
<cr>
<id>1</id>
<release>Aa</release>
<release>Ab</release>
<release>Ad</release>
</cr>
<cr>
<id>2</id>
<release>Ba</release>
<release>Bb</release>
<release>Bd</release>
</cr>
<cr>
<id>3</id>
<release>C</release>
</cr>
<cr>
<id>4</id>
<release>D</release>
</cr>
</root>
注意:许多不同名称的元素可能会被相同的转换所取代。
如果我们有此映射文件:
<map>
<release old="A">
<release>Aa</release>
<release>Ab</release>
<release>Ad</release>
</release>
<release old="B">
<release>Ba</release>
<release>Bb</release>
<release>Bd</release>
</release>
<history old="p">
<history>Pp</history>
<history>Pq</history>
<history>Pr</history>
</history>
</map>
和此源XML文档:
<root>
<cr>
<id>1</id>
<history>p</history>
<release>A</release>
</cr>
<cr>
<id>2</id>
<history>q</history>
<release>B</release>
</cr>
<cr>
<id>3</id>
<history>r</history>
<release>C</release>
</cr>
<cr>
<id>4</id>
<history>t</history>
<release>D</release>
</cr>
</root>
然后进行此转换:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:variable name="vMap" select="document('mapping.xml')/*/*"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="release[. = document('mapping.xml')/*/release/@old]">
<xsl:copy-of select="$vMap[@old = current()]/*"/>
</xsl:template>
<xsl:template match="history[. = document('mapping.xml')/*/history/@old]">
<xsl:copy-of select="$vMap[@old = current()]/*"/>
</xsl:template>
</xsl:stylesheet>
应用于上述XML文档时,生成所需结果 - 其中映射和替换了多个不同名称的元素:
<root>
<cr>
<id>1</id>
<history>Pp</history>
<history>Pq</history>
<history>Pr</history>
<release>Aa</release>
<release>Ab</release>
<release>Ad</release>
</cr>
<cr>
<id>2</id>
<history>q</history>
<release>Ba</release>
<release>Bb</release>
<release>Bd</release>
</cr>
<cr>
<id>3</id>
<history>r</history>
<release>C</release>
</cr>
<cr>
<id>4</id>
<history>t</history>
<release>D</release>
</cr>
</root>
最后:可以在XSLT 2.0中编写更简短,更通用的转换:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:variable name="vMap" select="document('mapping.xml')/*/*"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match=
"*[. = $vMap[name() eq name(current())]/@old]">
<xsl:copy-of select="$vMap[name() eq name(current()) and @old eq current()]/*"/>
</xsl:template>
</xsl:stylesheet>
请注意:此转换中没有硬编码元素名称!
更大的优势:我们可以修改转换,因此我们可以将映射文档的URI作为调用转换的全局参数传递 - 因此我们可以进行单一的泛型转换适用于任何未知的预先映射。
只有这些是必需的更改:
<xsl:param name="pmapUrl" select="'file:///c:/temp/mapping.xml'"/>
<xsl:variable name="vMap" select="document($pmapUrl)/*/*"/>
完整转换(全局参数pmapUrl
可以并且通常由转化的调用者动态指定:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:param name="pmapUrl" select="'file:///c:/temp/mapping.xml'"/>
<xsl:variable name="vMap" select="document($pmapUrl)/*/*"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match=
"*[for $name in name()
return
. = $vMap[name() eq $name]/@old]">
<xsl:copy-of select="$vMap[@old = current()]/*"/>
</xsl:template>
</xsl:stylesheet>