删除保留子节点的XML父节点

时间:2016-10-12 02:34:46

标签: c# for-loop foreach

如果我(例如)具有以下结构的XML文件:

<Parent1>
      <listChild>
           <child>
               <listchild2>
                    <child2>
                    <child2>
                    <child2>
               </listchild2>
           </child>
           <child>
                <listchild2>
                     <child2>
                     <child2>
                     <child2>
                </listchild2>
           </child>
      </listchild>
</parent1>

我想删除预期输出的listChildlistChild2

 <Parent>
       <child>
          <child>
          <child>
          <child>
       </child>
       <child>
          <child>
          <child>
          <child>
       </child>
</parent>

我试过System.Xml.Linq,就像这样:

public void removeParentNode(String filename)
{
    XDocument xdoc = XDocument.Load(filename);

    //remove parent1 
    var child= xdoc.Descendants("child");                       
    XElement dcuManager = new XElement("parent1 ");
    parent1 .Add(child);

    XDocument xdoc1 = new XDocument(dcuManager);
}

但是代码只删除了外部列表。

有没有办法只删除<listchild></listchild>标记,保留其所有子节点?

------------------------更新---------------------- ---------------

上面的xml代码是非常简单的例子 我的xml代码是:

<?xml version="1.0" encoding="utf-8"?>
<DcuManager xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <listDcu>
    <Dcu id="dcu1 id" mode="dcu1 mode" port="dcu1 port">
      <modemMgr>
        <listModem>
          <Modem id="Modem1 id" port="modem 1 port" communicationStatus="modem 1 mode">
            <meterManager>
              <listMeter>
                <Meter id="Meter 1 id" port="Meter 1 port" mac="Meter 1 mode" />
              </listMeter>
            </meterManager>
          </Modem>
          <Modem id="Modem2 id" port="modem 2 port" communicationStatus="modem 2 mode">
            <meterManager>
              <listMeter>
                <Meter id="Meter 2 id" port="Meter 2 port" mac="Meter 2 mode" />
              </listMeter>
            </meterManager>
          </Modem>
        </listModem>
      </modemMgr>
    </Dcu>
    <Dcu id="dcu2 id" mode="dcu2 mode" port="dcu2 port">
      <modemMgr>
        <listModem>
          <Modem id="Modem3 id" port="modem 3 port" communicationStatus="modem 3 mode">
            <meterManager>
              <listMeter>
                <Meter id="Meter 3 id" port="Meter 3 port" mac="Meter 3 mode" />
              </listMeter>
            </meterManager>
          </Modem>
          <Modem id="Modem4 id" port="modem 4 port" communicationStatus="modem 4 mode">
            <meterManager>
              <listMeter>
                <Meter id="Meter 4 id" port="Meter 4 port" mac="Meter 4 mode" />
              </listMeter>
            </meterManager>
          </Modem>
        </listModem>
      </modemMgr>
    </Dcu>
    <Dcu id="dcu3 id" mode="dcu3 mode" port="dcu3 port">
      <modemMgr>
        <listModem>
          <Modem id="Modem5 id" port="modem 5 port" communicationStatus="modem 5 mode">
            <meterManager>
              <listMeter>
                <Meter id="Meter 5 id" port="Meter 5 port" mac="Meter 5 mode" />
              </listMeter>
            </meterManager>
          </Modem>
          <Modem id="Modem6 id" port="modem 6 port" communicationStatus="modem 6 mode">
            <meterManager>
              <listMeter>
                <Meter id="Meter 6 id" port="Meter 6 port" mac="Meter 6 mode" />
              </listMeter>
            </meterManager>
          </Modem>
        </listModem>
      </modemMgr>
    </Dcu>
  </listDcu>
</DcuManager>

此代码将c#class转换为xml。 我想删除dcuMgr,modemMgr,meterMgr保持子节点。 我怎么样?

1 个答案:

答案 0 :(得分:0)

您的规格不是很清楚。 XML本身没有&#34; list&#34;的概念。任何元素都可以包含任意数量的子元素,而XML并不关心元素的名称。使用&#34; list&#34;在一个元素中实际上并不是一个列表。

此外,在您的示例XML中,您会显示两种不同的&#34; child&#34;节点,外部名为child,内部名为child2。但是在您想要的输出中,您只有名称childchild2节点似乎已被child节点替换。

不幸的是,您展示的XML甚至不是有效的XML。很明显,您没有向我们提供真正的 XML示例,因此更难以理解您尝试做的事情。

因此,考虑到所有这些,我将指出,基于递归,您希望将相同算法应用于一系列嵌套对象的基本方法。即您希望以递归方式选择要保留的节点,并对它们应用相同的删除逻辑。

这是一个Complete, Minimal, and Verifiable code example(即首先应该包含在问题中的内容),它说明了这个基本概念:

class Program
{
    const string _kxmlInput =
        @"<parent1>
      <listchild>
           <child>
               <listchild2>
                    <child/>
                    <child/>
                    <child/>
               </listchild2>
           </child>
           <child>
                <listchild2>
                     <child/>
                     <child/>
                     <child/>
                </listchild2>
           </child>
      </listchild>
</parent1>";

    static void Main(string[] args)
    {
        Console.WriteLine(removeParentNode(_kxmlInput));
    }

    static string removeParentNode(string xml)
    {
        StringReader reader = new StringReader(xml);

        XDocument xdoc = XDocument.Load(reader);

        //remove parent1 
        XDocument xdoc1 = new XDocument(KeepDescendants(xdoc.Root, "child"));

        StringBuilder sb = new StringBuilder();
        XmlWriterSettings settings = new XmlWriterSettings { Indent = true };

        using (XmlWriter xmlWriter = XmlWriter.Create(sb, settings))
            xdoc1.WriteTo(xmlWriter);

        return sb.ToString();
    }

    private static XElement KeepDescendants(XElement node, string descendantName)
    {
        var child = node.Descendants(descendantName).Select(c => KeepDescendants(c, descendantName));

        if (!child.Any())
        {
            return node;
        }

        XElement newParent = new XElement(node.Name);

        newParent.Add(child);

        return newParent;
    }
}

如果您还有其他一些行为,您应该能够调整上面显示的基本技术,以实现您真正想做的任何事情。