【问题标题】:how to remove duplicate values in a XML file and keep the last one?如何删除 XML 文件中的重复值并保留最后一个?
【发布时间】:2012-03-15 00:20:27
【问题描述】:

我需要抑制 XML 文件中的所有重复值并保留最终值(参考目标文件)。

请帮忙,因为我不知道是否应该使用 xslt、python 或任何 .NET API

这里是源文件:

<?xml version="1.0" encoding="ISO-8859-1"?>
<catalog>
<cd>
    <artist>Bob Dylan</artist>
</cd>
<cd>
    <title>Hide your heart</title>
</cd>
<cd>
    <title>old_value</title>
    <title>inbetween_value</title>
    <title>new_value</title>
</cd>
</catalog>

预期的目标文件:

<?xml version="1.0" encoding="ISO-8859-1"?>
<catalog>
<cd>
    <artist>Bob Dylan</artist>
</cd>
<cd>
    <title>Hide your heart</title>
</cd>
<cd>
    <title>new_value</title>
</cd>
</catalog>

【问题讨论】:

    标签: .net python xml xslt duplicates


    【解决方案1】:

    有一个非常简单(没有明确的条件,没有轴)XSLT 解决方案

    <xsl:stylesheet version="1.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     <xsl:output encoding="ISO-8859-1"/>
     <xsl:strip-space elements="*"/>
    
     <xsl:template match="node()|@*">
         <xsl:copy>
           <xsl:apply-templates select="node()|@*"/>
         </xsl:copy>
     </xsl:template>
    
     <xsl:template match="cd/title[not(position() = last())]"/>
    </xsl:stylesheet>
    

    当此转换应用于提供的 XML 文档时

    <catalog>
        <cd>
            <artist>Bob Dylan</artist>
        </cd>
        <cd>
            <title>Hide your heart</title>
        </cd>
        <cd>
            <title>old_value</title>
            <title>inbetween_value</title>
            <title>new_value</title>
        </cd>
    </catalog>
    

    产生想要的正确结果

    <?xml version="1.0" encoding="ISO-8859-1"?>
    <catalog>
       <cd>
          <artist>Bob Dylan</artist>
       </cd>
       <cd>
          <title>Hide your heart</title>
       </cd>
       <cd>
          <title>new_value</title>
       </cd>
    </catalog>
    

    【讨论】:

    • 目前尚不清楚 OP 是要删除所有重复项还是仅删除 title 重复项。我认为您的代码仅适用于后者,不是吗?
    • 是的,它工作得很好,但是第一行被删除了:
    • @laurentngu:如果您真的需要 XML 声明,请将 &lt;xsl:output/&gt; 替换为:&lt;xsl:output encoding="ISO-8859-1"/&gt;
    • @laurentngu:我更新了我的答案,现在它生成了想要的 XML 声明。
    【解决方案2】:

    XSLT 1 版本:

    <xsl:stylesheet version="1.0"
            xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    
    <xsl:template match="*">
     <xsl:copy>
      <xsl:copy-of select="@*"/>
      <xsl:apply-templates/>
     </xsl:copy>
    </xsl:template>
    <xsl:template match="cd/*">
     <xsl:if test="not(following-sibling::*[name()=name(current())])">
      <xsl:copy-of select="."/>
     </xsl:if>
    </xsl:template>
    </xsl:stylesheet>
    

    【讨论】:

      【解决方案3】:

      您可以使用任何您想要的技术。如果您的要求是“对于每个 cd 元素,只保留重复子元素名称的最后一个值”,这是一个 LINQ to XML 解决方案,假设您有一个名为 XDocumentoldDoc

      var scrubbedDoc = new XDocument(new XElement("catalog",
          from cd in oldDoc.Element("catalog").Elements("cd")
          select new XElement("cd",
              from elementsGroupedByName in cd.Elements().ToLookup(e => e.Name)
              select elementsGroupedByName.Last())));
      

      【讨论】:

        【解决方案4】:

        要删除所有重复项,您可以在标签名称和元素之间保留一个字典。在具有 minidom 的 Python 中:

        xml = """<?xml version="1.0" encoding="ISO-8859-1"?>
        <catalog>
        <cd>
          <artist>Bob Dylan</artist>
        </cd>
        <cd>
          <title>Hide your heart</title>
        </cd>
        <cd>
          <artist>Bob Dylan</artist>
          <title>old_value</title>
          <title>inbetween_value</title>
          <title>new_value</title>
          <artist>Freddie Mercury</artist>
          <title>Don't stop me now</title>
        </cd>
        </catalog>"""
        
        from xml.dom import minidom
        doc = minidom.parseString(xml)
        
        for cd in doc.getElementsByTagName("cd"):
          elements = {}
          for element in cd.childNodes:
            if element.nodeType is not minidom.Node.ELEMENT_NODE:
              continue
            if element.tagName in elements:
              cd.removeChild(element)
              print("Removed duplicated " + element.tagName)
            elements[element.tagName] = element
        
        # doc.writexml(open("/path/to/file", "w"))
        

        【讨论】:

          猜你喜欢
          • 2013-07-10
          • 2022-07-19
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-09-01
          • 2021-01-19
          • 2015-09-27
          相关资源
          最近更新 更多