我有两个需要以特殊方式组合的XML文档。
作为一个简单的例子,我将两个文件放在一起:
<?xml version="1.0" encoding="utf-8" ?>
<data>
<config1>
<option1 type="a">A</option1>
<option2 type="b">B</option2>
<option3 type="c">C</option3>
</config1>
<config2>
<option2 type="bb">BB</option2>
<option4>D</option4>
</config2>
</data>
所以,我需要将 config1 和 config2 合并到这个结果中:
<?xml version="1.0" encoding="UTF-8"?>
<data>
<config>
<option1 type="a">A</option1>
<option2 type="bb">BB</option2>
<option3 type="c">C</option3>
<option4>D</option4>
</config>
</data>
转换规则是:
我是按照XSLT制作的:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/*">
<xsl:copy>
<config>
<!-- Select options from config 1. -->
<xsl:for-each select="config1/*">
<xsl:choose>
<!-- Leave option as is. -->
<xsl:when test="not(/data/config2/*[name() = name(current())])">
<xsl:copy-of select="."/>
</xsl:when>
<!-- Overwrite option. -->
<xsl:otherwise>
<xsl:copy-of select="/data/config2/*[name() = name(current())]"/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
<!-- Select options from config 2. -->
<xsl:for-each select="config2/*">
<!-- Append "new" option -->
<xsl:if test="not(/data/config1/*[name()=name(current())])">
<xsl:copy-of select="."/>
</xsl:if>
</xsl:for-each>
</config>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
它有效,但看起来很蹩脚。
许多XSL专家更喜欢将for-templates替换为for-each。
是否可以以这种方式重写我的模板?
答案 0 :(得分:2)
作为一个简单的例子,我将两个文件放在一起:
这不是一个好主意,因为处理两个文档与处理同一文档中的两个节点集不同。因此,假设您处理的文档是:
<?xml version="1.0" encoding="utf-8" ?>
<data>
<config1>
<option1 type="a">A</option1>
<option2 type="b">B</option2>
<option3 type="c">C</option3>
</config1>
</data>
还有另一份文件:
<强> file2.xml 强>
<?xml version="1.0" encoding="utf-8" ?>
<data>
<config2>
<option2 type="bb">BB</option2>
<option4>D</option4>
</config2>
</data>
您可以使用以下样式表:
XSLT 1.0
<?xml version="1.0" encoding="UTF-8"?>
<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:variable name="config2" select="document('file2.xml')/data/config2" />
<xsl:template match="/">
<data>
<config>
<xsl:apply-templates select="data/config1/*[not(name()=name($config2/*))] | $config2/*"/>
</config>
</data>
</xsl:template>
<xsl:template match="data/*/*">
<xsl:copy-of select="."/>
</xsl:template>
</xsl:stylesheet>
获得此结果:
<?xml version="1.0" encoding="UTF-8"?>
<data>
<config>
<option1 type="a">A</option1>
<option3 type="c">C</option3>
<option2 type="bb">BB</option2>
<option4>D</option4>
</config>
</data>