【问题标题】:Convert first child XML node to become a parent node for all of its siblings将第一个子 XML 节点转换为所有兄弟节点的父节点
【发布时间】:2014-01-14 16:13:03
【问题描述】:

我需要移动特定的第一个子节点并将其转换为父节点,如下所示:

我已更改 XML 以使其更清晰。

原始 XML

<root version="1.0">
    <body>
        <nodeList projectName="testing charcharistics">
            <node modelDescription="I'm parent node which needs to be removed">
                <node modelCatalogNum="I'm First Son node to become parent node" attr1="1" attr2="2" ....... />
                <node modelCatalogNum="NETDIR-1" />
                <node modelCatalogNum="NETDIR-2" />
                <node modelCatalogNum="NETDIR-3" />
                .
                .
                .
                .
            </node>
        </nodeList>
    </body>
</root>

输出 XML

<root version="1.0">
    <body>
        <nodeList projectName="testing charcharistics">
            <node modelCatalogNum="I'm First Son node to become parent node" attr1="1" attr2="2" ....... />
                <node modelCatalogNum="NETDIR-1" />
                <node modelCatalogNum="NETDIR-2" />
                <node modelCatalogNum="NETDIR-3" />
                .
                .
                .
                .
            </node>
        </nodeList>
    </body>
</root>

如您所见,第一个子节点已成为父节点。

我需要 C# 代码中的通用解决方案,其中包含以下内容 步骤。

  1. 第一个儿子将成为其所有兄弟节点的父节点
  2. 移除父节点。

谁能帮忙?

【问题讨论】:

  • modelDescription="My Model Description" 发生了什么?
  • Hi Scription,如果您得到答案,请将其标记为正确的,谢谢
  • 向右滚动可以找到modelDescription="My Model Description"。

标签: c# xml


【解决方案1】:

这是您可以单独删除自闭标签的解决方案。

Test.xml - 您的原始 xml 和 Test1.xml - 修改后的 xml

        XmlDocument doc = new XmlDocument();
        doc.Load(@"E:\Test.xml");

        XmlNodeList elementList = doc.GetElementsByTagName("node");

        for (int i = 0; i < elementList.Count; i++)
        {
            if (elementList[0].Attributes["modelDescription"].Value == "My Model Description")
            {
                elementList[0].Attributes["modelDescription"].Value = elementList[1].Attributes["modelDescription"].Value;

                XmlAttribute newAttribute1 = doc.CreateAttribute("instanceName");
                newAttribute1.Value = elementList[1].Attributes["instanceName"].Value;
                elementList[0].Attributes.Append(newAttribute1);

                XmlAttribute newAttribute2 = doc.CreateAttribute("modelCatalogNum");
                newAttribute2.Value = elementList[1].Attributes["modelCatalogNum"].Value;
                elementList[0].Attributes.Append(newAttribute2);

                elementList[1].ParentNode.Attributes.Remove(elementList[0].Attributes["quantity"]);

                elementList[0].FirstChild.RemoveAll();
            }
        }

        doc.Save(@"E:\Test1.xml");  

【讨论】:

  • 感谢您的努力,但是您的解决方案并不通用,因为我需要它,所以它毕竟不是很有帮助。
【解决方案2】:

这个通用方法怎么样:

private static void Invert(XmlNode startingNode, string path)
{
    XmlNode node = startingNode.SelectSingleNode(path);
    if (node != null)
    {
        XmlNode firstChild = node.SelectSingleNode("*");

        if(firstChild != null)
        {
            XmlNodeList others = 
                 node.SelectNodes("node()[not(self::*)] | *[position() > 1]");
            foreach (XmlNode other in others)
            {
                firstChild.AppendChild(other);
            }
            node.ParentNode.ReplaceChild(firstChild, node);
        }
    }
}

你可以这样称呼它:

 Invert(doc, "/root/body/nodeList/node");

或者,您可以使用 XSLT:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>

  <xsl:template match="@* | node()">
    <xsl:copy>
      <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="nodeList/node">
    <xsl:apply-templates select="*[1]" mode="newParent" />
  </xsl:template>

  <xsl:template match="*" mode="newParent">
    <xsl:copy>
      <xsl:apply-templates select="@*" />
      <xsl:apply-templates select="../node()[generate-id() !=
                                             generate-id(current())]" />
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

【讨论】:

  • 谢谢,非常优雅的解决方案
【解决方案3】:

这个怎么样?

XmlDocument doc = new XmlDocument();
        doc.Load("Test.xml");

您可以发送一个变量来确定要删除的节点 XmlNodeList elementList = doc.GetElementsByTagName("node");

只是为了显示列表

        foreach (XmlNode node in elementList)
        {                
            Console.Write(node.Name + " ");
            foreach (XmlAttribute attr in node.Attributes)
            {
                Console.Write(attr.Name + ":" + attr.Value + " ");
            }
            Console.WriteLine();
        }

通用删除 - 基本上从父级删除属性并从第一个子级添加属性,然后删除子级

        var firstChild = elementList[0].FirstChild;
        elementList[0].Attributes.RemoveAll();
        for (int i = 0; i < firstChild.Attributes.Count; i++)
        {
            XmlAttribute item = doc.CreateAttribute(firstChild.Attributes[i].Name);
            item.Value = firstChild.Attributes[i].Value;
            elementList[0].Attributes.Append(item);
        }
        elementList[0].RemoveChild(firstChild);

只是为了显示列表

        Console.WriteLine();
        foreach (XmlNode node in elementList)
        {                
            Console.Write(node.Name + " ");
            foreach (XmlAttribute attr in node.Attributes)
            {
                Console.Write(attr.Name + ":" + attr.Value + " ");
            }
            Console.WriteLine();
        }

        Console.ReadLine();

【讨论】:

    猜你喜欢
    • 2021-11-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-08
    • 2014-02-05
    相关资源
    最近更新 更多