我在XML文件中有以下结构:
<root name="name1">
<layer1 name="name2">
<layer2 attribute="sowhat">
</layer2>
</layer1>
</root>
<root name="name1">
<layer1 name="name2">
<layer2 attribute="justit">
</layer2>
</layer1>
</root>
<root name="name1">
<layer1 name="name2">
<layer2 attribute="yeaha">
</layer2>
</layer1>
</root>
<root name="name2123">
<layer1 name="name2">
<layer2 attribute="itis">
</layer2>
</layer1>
</root>
我希望得到一个看起来像的结果:
<root name="name1">
<layer1 name="name2">
<layer2 attribute="sowhat"></layer2>
<layer2 attribute="justit"></layer2>
<layer2 attribute="yeaha"></layer2>
</layer1>
</root>
<root name="name2123">
<layer1 name="name2">
<layer2 attribute="itis">
</layer2>
</layer1>
</root>
所以我想尽可能地合并和组合节点。我还没有使用XSLT,尝试过,但我不明白,甚至不是一般的想法。还有其他想法或工具吗?
由于
答案 0 :(得分:2)
对于它的价值,这是一种在XSLT 1.0中执行此操作的方法。
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes" />
<xsl:strip-space elements="*" />
<xsl:key name="name" match="*[@name]" use="
concat(@name, '|', ancestor::*[1]/@name, '|', ancestor::*[2]/@name)
" />
<xsl:template match="node() | @*">
<xsl:copy>
<xsl:apply-templates select="node() | @*" />
</xsl:copy>
</xsl:template>
<xsl:template match="*[@name]">
<xsl:variable name="myKey" select="
concat(@name, '|', ancestor::*[1]/@name, '|', ancestor::*[2]/@name)
" />
<xsl:variable name="myGroup" select="key('name', $myKey)" />
<xsl:if test="generate-id() = generate-id($myGroup[1])">
<xsl:copy>
<xsl:copy-of select="@*" />
<xsl:apply-templates select="$myGroup/*" />
</xsl:copy>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
输出
<roots>
<root name="name1">
<layer1 name="name2">
<layer2 attribute="sowhat"/>
<layer2 attribute="justit"/>
<layer2 attribute="yeaha"/>
</layer1>
</root>
<root name="name2123">
<layer1 name="name2">
<layer2 attribute="itis"/>
</layer1>
</root>
</roots>
XSLT的关键特性是能够在相对较少的代码行中表达复杂的转换。上面的转换是29行代码,你可以进一步挤压它。
我认为XSLT中的速成课程超出了本答案的范围。除此之外,互联网上还有无数的XSLT速成课程。
所以我要做的就是概述这里发生的事情。
首先,我已经为您的输入定义了两类元素 - 可合并的元素和不可合并的元素。我已经定义了所有具有@name
属性的元素可以合并。
@name
的节点)都按原样复制。第一个<xsl:template>
就是这样做的(它是身份模板)。@name
属性值的元素。
@name
属性的串联。concat(@name, '|', ancestor::*[1]/@name, '|', ancestor::*[2]/@name)
)的组。 sowhat
的父级的组名(键)为name2|name1||
,这适用于该逻辑组中的其他<layer2>
。@name
的元素时,它就会出现
$myKey
)。$myGroup
)的元素组。$myGroup/*
)。我的代码中有一些假设/限制可能不一定与您的输入一致。
@name
合并,而不是由其他一些属性合并。@name
祖先的元素没有特殊属性,因此抛弃某个组中除第一个元素之外的每个元素都不会导致数据丢失。<layer>
@name
内<layer>
没有@name
阅读建议