我想从XML结构中删除重复的节点



我想使用XSLT从下面的XML中删除重复的节点。我正在使用XSLT将一个XML转换为另一个XML结构。我怎样才能得到想要的结果?

我有一段代码,它是从一个应用程序生成的,它将进入一个不同的应用程序。因此,来自源应用程序的数据包含一些冗余节点,如下例所示。因此,我必须将转换后的XML放置到目标应用程序将使用的文件夹中

安排非常简单

例如,我正在像这样的xml结构中寻找一个重复的文件名

<file>
<name>some-name</name>
</file>

我做了一把这样的钥匙:

<xsl:key name="dupfile" match="file" use="name"/>

然后我创建了一个类似的模板

<xsl:template match="file[not(generate-id() = generate-id(key('dupfile', name)[1]))]">
</xsl:template

它被称为Muenchian方法,请在此处查找有关信息:http://www.jenitennison.com/xslt/grouping/muenchian.html

如果(像在模板中一样(过滤value元素就足够了,那么这就可以了。

<xsl:stylesheet 
version="2.0" 
xmlns:infor="http://schema.infor.com/InforOAGIS/2" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:xs="http://www.w3.org/2001/XMLSchema" 
exclude-result-prefixes="#all">
<xsl:output method="xml" encoding="UTF-8" indent="no" byte-order-mark="no"/>
<xsl:strip-space elements="*"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>

<xsl:template match="infor:Concur_LN_ServiceData">
<xsl:if test="not(following-sibling::infor:Concur_LN_ServiceData[infor:Value=current()/infor:Value])">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:if>       
</xsl:template>
</xsl:stylesheet>

xslt:中有2个问题

  1. 命名空间:"http://schema.infor.com/InforOAGIS/2"没有前缀:参见此示例

  2. XPath:following::Concur_LN_ServiceData[Concur_LN_ServiceData找不到任何内容,因为没有包含元素Concur_LN_ServiceDataConcur_LN_ServiceData

并声明您实际使用的命名空间。。。。但这只是我个人的喜好

编辑

如果你处理的是大型xml,最好对每个组使用(比如@michael.hor257k(:

<xsl:stylesheet 
version="2.0" 
xmlns:infor="http://schema.infor.com/InforOAGIS/2" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:xs="http://www.w3.org/2001/XMLSchema" 
exclude-result-prefixes="#all">
<xsl:output method="xml" encoding="UTF-8" indent="no" byte-order-mark="no"/>
<xsl:strip-space elements="*"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="infor:DataArea">
<xsl:copy>
<xsl:apply-templates select="infor:Show"/>
<xsl:for-each-group select="infor:Concur_LN_ServiceData" group-by="infor:Value">
<xsl:sequence select="current-group()[1]"/>
</xsl:for-each-group>
</xsl:copy> 
</xsl:template>

</xsl:stylesheet>

最新更新