我想根据以下规则将两个文件A.xml和map.xml与"Node"元素合并(节点由@Name区分):
例:
map.xml:
<?xml version="1.0"?>
<Node Name="ParentNode">
<Node Name="Child1" Src="Child1/"/>
<Node Name="Child2" Src="Child2/"/>
<Node Name="Child3" Src="Child3/"/>
<Node Name="Child4">
<Node Name="Child4_Sub1" />
<Node Name="Child4_Sub2" Src="Child4_Sub2/"/>
</Node>
<Node Name="Child5" />
</Node>
Run Code Online (Sandbox Code Playgroud)
A.XML:
<Node Name="ParentNode">
<Node Name="Child4">
<Node Name="Child4">
<Node Name="Child4_Sub1">
<!-- Here are many other elements -->
</Node>
</Node>
</Node>
<!-- Here are many other elements -->
<Node Name="Child1">
<!-- Here are many other elements -->
</Node>
<!-- Here are many other elements -->
<Node Name="ChildFoo">
<!-- Here are many other elements -->
</Node>
</Node>
Run Code Online (Sandbox Code Playgroud)
结果应该是:
<Node Name="ParentNode">
<Node Name="Child4">
<Node Name="Child4">
<Node Name="Child4_Sub1">
<!-- Here are many other elements -->
</Node>
<Node Name="Child4_Sub2" />
</Node>
</Node>
<!-- Here are many other elements -->
<Node Name="Child1" Src="Child1" />
<!-- Here are many other elements -->
<Node Name="Child2" Src="Child2" />
<Node Name="Child3" Src="Child3" />
</Node>
Run Code Online (Sandbox Code Playgroud)
我的XSLT脚本是:
<?xml version="1.0"?>
<xsl:stylesheet version="2.0">
<xsl:param name="mapFile" required="yes"/>
<xsl:variable name="MapDiagram" select="document($mapFile,/*)"/>
<xsl:variable name="CurrentDocument" select="/" />
<!-- handle Node elements in A.xml -->
<xsl:template match="Node">
<xsl:variable name="MyName" select="@Name"/>
<xsl:choose>
<xsl:when test="$MapDiagram//Node[@Name = $MyName]">
<xsl:choose>
<xsl:when test="$MapDiagram//Node[@Name = $MyName]/@Src">
<xsl:copy-of select="$MapDiagram//Node[@Name = $MyName]"/>
</xsl:when>
<xsl:otherwise>
<Node Name="{@Name}" Type="{@Type}">
<xsl:apply-templates/>
<xsl:apply-templates select="$MapDiagram//Node[@Name = $MyName]" mode="MapDiagram" />
</Node>
</xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:otherwise>
<xsl:message terminate="no">WARNING: Node "<xsl:value-of select="@Name"/>" not found in map file, ignoring</xsl:message>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<!-- handle Node elements from map file -->
<xsl:template match="Node" mode="MapDiagram">
<xsl:variable name="MyName" select="@Name"/>
<xsl:choose>
<xsl:when test="not($CurrentDocument//Node[@Name = $MyName])">
<xsl:copy-of select="."/>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates mode="MapDiagram" />
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<!-- Copy all other elements in between -->
<xsl:template match="*[name() != 'Node']">
<xsl:copy-of select="."/>
</xsl:template>
</xsl:stylesheet>
Run Code Online (Sandbox Code Playgroud)
该脚本工作正常.它处理A.xml并在map.xml中查找每个Node元素.由于可以混合@Src和非@ Src节点,因此可以递归调用它.
但是,此脚本生成:
<Node Name="ParentNode">
<Node Name="Child4">
<Node Name="Child4">
<Node Name="Child4_Sub1">
<!-- Here are many other elements -->
</Node>
<Node Name="Child4_Sub2" />
</Node>
</Node>
<!-- Here are many other elements -->
<Node Name="Child1" Src="Child1" />
<!-- Here are many other elements -->
<Node Name="Child2" Src="Child2" />
<Node Name="Child3" Src="Child3" />
<Node Name="Child4_Sub2" />
</Node>
Run Code Online (Sandbox Code Playgroud)
因此,Child4_Sub2生成两次是没有意义的,因为Child4_Sub2无论如何都需要Child4作为父级!但到目前为止,我发现没有办法阻止这个元素被打印出来.
你有什么提示吗?
此致,divB
更改:
<xsl:apply-templates mode="MapDiagram" select=
"$MapDiagram//Node[@Name = $MyName]"/>
Run Code Online (Sandbox Code Playgroud)
至:
<xsl:if test="not(@Name = ancestor::Node/@Name)">
<xsl:apply-templates mode="MapDiagram" select=
"$MapDiagram//Node[@Name = $MyName]"/>
</xsl:if>
Run Code Online (Sandbox Code Playgroud)
这是一个完整的解决方案:
<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="mapFile"
select="'file:///c:/temp/delete/map.xml'"/>
<xsl:variable name="MapDiagram" select="document($mapFile,/*)"/>
<xsl:variable name="CurrentDocument" select="/" />
<!-- handle Node elements in A.xml -->
<xsl:template match="Node">
<xsl:variable name="MyName" select="@Name"/>
<xsl:choose>
<xsl:when test="$MapDiagram//Node[@Name = $MyName]">
<xsl:choose>
<xsl:when test="$MapDiagram//Node[@Name = $MyName]/@Src">
<xsl:copy-of select="$MapDiagram//Node[@Name = $MyName]"/>
</xsl:when>
<xsl:otherwise>
<Node Name="{@Name}" Type="{@Type}">
<xsl:apply-templates/>
<xsl:if test="not(@Name = ancestor::Node/@Name)">
<xsl:apply-templates mode="MapDiagram" select=
"$MapDiagram//Node[@Name = $MyName]"
/>
</xsl:if>
</Node>
</xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:otherwise>
<xsl:message terminate="no">WARNING: Node "<xsl:value-of select="@Name"/>" not found in map file, ignoring</xsl:message>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<!-- handle Node elements from map file -->
<xsl:template match="Node" mode="MapDiagram">
<xsl:variable name="MyName" select="@Name"/>
<xsl:choose>
<xsl:when test="not($CurrentDocument//Node[@Name = $MyName])">
<xsl:copy-of select="."/>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates mode="MapDiagram" />
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<!-- Copy all other elements in between -->
<xsl:template match="*[name() != 'Node']">
<xsl:copy-of select="."/>
</xsl:template>
</xsl:stylesheet>
Run Code Online (Sandbox Code Playgroud)
将此转换应用于提供的XML文档时:
<Node Name="ParentNode">
<Node Name="Child4">
<Node Name="Child4">
<Node Name="Child4_Sub1"/>
</Node>
</Node>
<Node Name="Child1"/>
<Node Name="ChildFoo"/>
</Node>
Run Code Online (Sandbox Code Playgroud)
提供的"map.xml"是at C:\temp\delete\map.xml:
<Node Name="ParentNode">
<Node Name="Child1" Src="Child1/"/>
<Node Name="Child2" Src="Child2/"/>
<Node Name="Child3" Src="Child3/"/>
<Node Name="Child4">
<Node Name="Child4_Sub1" />
<Node Name="Child4_Sub2" Src="Child4_Sub2/"/>
</Node>
<Node Name="Child5" />
</Node>
Run Code Online (Sandbox Code Playgroud)
产生了想要的结果(不包含不需要的重复):
<Node Name="ParentNode" Type="">
<Node Name="Child4" Type="">
<Node Name="Child4" Type="">
<Node Name="Child4_Sub1" Type=""/>
</Node>
<Node Name="Child4_Sub2" Src="Child4_Sub2/"/>
</Node>
<Node Name="Child1" Src="Child1/"/>
<Node Name="Child2" Src="Child2/"/>
<Node Name="Child3" Src="Child3/"/>
<Node Name="Child4_Sub2" Src="Child4_Sub2/"/>
<Node Name="Child5"/>
</Node>
Run Code Online (Sandbox Code Playgroud)
一般说明:提供的代码非常复杂和混乱 - 可能还有其他逻辑问题.没有使用XSLT 2.0语言功能 - 这本质上是一个XSLT 1.0解决方案.以更好的形式重写代码是个好主意.
| 归档时间: |
|
| 查看次数: |
3243 次 |
| 最近记录: |