【问题标题】:I want to remove duplicate nodes from a XML structure我想从 XML 结构中删除重复节点
【发布时间】:2021-08-06 17:44:57
【问题描述】:

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

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

【问题讨论】:

  • 请就您在尝试完成此操作时遇到的困难提出一个具体问题。否则,看起来您只是在寻找某人为您编写代码。还将示例减少到演示问题所需的最低限度 - 请参阅:minimal reproducible example
  • 我尝试过使用多种东西,但未能获得所需的结果
  • 向我们展示你的尝试
  • OP,编辑,请不要破坏帖子。如果有敏感数据,请标记mod注意并解释。在 SO 上发布的任何内容都包含在 CC BY-SA 中:creativecommons.org/licenses/by-sa/4.0
  • 请在帮助中心查看:I've thought better of my question; can I delete it?。我们支持删除和编辑真正敏感的信息。但是,我们不支持大规模销毁问题和/或相关答案。您应该努力以删除敏感信息但保留问题的实质和微妙之处的方式编辑问题。完成后,您可以标记以要求修改。允许对答案中的信息进行编辑和编辑,但答案必须保留其有用性。

标签: xml xslt xslt-2.0


【解决方案1】:

安排起来很简单

例如,我正在寻找这样的 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

【讨论】:

  • XSLT 1.0 中需要 Muenchian(不是 München)方法。这个问题标记为 xslt-2.0,其中存在更好的内置方法。
  • @Soumya.r:我已将这篇文章恢复为原始版本。这里没有任何可以合理地被视为知识产权的内容。
  • 如果您想删除部分问题,请对其进行编辑(只是删除机密数据,而不是整个代码)并标记 mod,正如您被告知的那样。谢谢!
【解决方案2】:

如果(就像在您的模板中一样)过滤值元素就足够了,那么这将起作用。

<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”没有前缀:see this example

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

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

编辑

如果您正在处理大型 xml,最好使用 for-each-group(就像 @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>

【讨论】:

  • 这是一种非常低效的方法。为什么你不使用xsl:for-each group - 特别是。在您已经指出它是正确的解决方案之后?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-04-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-11-13
相关资源
最近更新 更多