我在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,尝试过它,但是我不理解它,甚至没有一般的想法。还有其他的想法或工具吗?
谢谢
发布于 2014-11-18 10:38:44
值得注意的是,这里有一种在XSLT1.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速成课程超出了这个答案的范围。除此之外,在Internet上有无数的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)。阅读建议
https://stackoverflow.com/questions/26990914
复制相似问题