XML文档拆分的算法

3

我希望能够按指定节点名称将一个XML文档分成多个XML文档(类似于string.Split(...)函数)。

例如:我有以下XML文档。

<root>
    <nodeA>
        Hello
    </nodeA>
    <nodeA>
        <nodeB>
            node b Text
        </nodeB>
        <nodeImage>
            image.jpg
        </nodeImage>
    </nodeA>
    <nodeA>
        node a text
    </nodeA>
</root>

我希望将这个XML文档按照“nodeImage”拆分为3个部分,并保留原始的XML结构。(注意:名称为“nodeImage”的节点可能出现在任何位置)
1. “nodeImage”之前的XML
2. “nodeImage”节点的XML
3. “nodeImage”之后的XML

对于示例XML,结果应该是:

XML文档1:

<root>
    <nodeA>
        Hello
    </nodeA>
    <nodeA>
        <nodeB>
            node b Text
        </nodeB>
    </nodeA>
</root>

XML文档2:

<root>
    <nodeA>
        <nodeImage>
            image.jpg
        </nodeImage>
    </nodeA>
</root>

XML文档3:

<root>
    <nodeA>
        node a text
    </nodeA>
</root>

请问是否有适用于此需求的好算法或现有的代码示例?

更新说明:
如果xml文档中只有一个名称为“nodeImage”的节点,则该xml文档应始终拆分为3个xml文档。


你能再看一下你的问题,并检查你想要实现的结果是否真的是你输入的文档吗?看起来“XML文档1”应该只有第一个“NodeA”... - Nir Kornfeld
这个答案有帮助吗?(http://stackoverflow.com/a/12672654/2065121) - Roger Rowland
请参见https://dev59.com/VGfWa4cB1Zd3GeqPeSk0。 - Mihai8
请展示您的实现代码。 - Nayan
@AlexCube,请检查我的答案,我认为它可以满足你的需求。 - Roman Pekar
5个回答

1
XElement xe = XElement.Load(XMLFile);

foreach(XElement newXE in xe.Elements("nodeA"))
{
    XElement root = new XElement("root",newXE);
    root.Save(newFile);
}

谢谢,但这不是我想要的。 - Alex Cube
你能具体一点吗? - Giannis Paraskevopoulos
输出结果与期望不符。请查看问题。 - Nayan

1
术语“split”有点令人困惑。在一个实例上进行拆分通常不会产生三个部分。
我首先尝试用Linq to xml的术语来定义您的问题。对于XDocument.Descendants("nodeImage")的每个出现,您想要创建:
  • 文档的副本,其中nodeImage父级具有已删除nodeImage和所有后续节点的nodeImage。此外,所有祖先必须删除所有nextnodes。
  • 文档的副本,其中nodeImage元素的所有祖先都已删除了所有XElement.NextNodes和XElement.PreviousNodes。
  • 在删除所有Ancestor PreviousNodes的XDocument的副本上再次运行此检查。
  • 如果未找到任何出现,则以其完整形式返回正在检查的文档。
XDocument的深层副本很容易。它有一个复制构造函数。当然,如果您的xml具有相当大的大小,则这将是一个内存猪。
但是,挑战在于在每个副本中定位您的节点。这个问题显示了如何获取元素的XPath。您可以使用它。

0

像这样,使用System.Xml.Linq

var doc = XDocument.Parse(stringxml);
var res = new List<XElement>();
var cur = new XElement("root");
foreach (var node in doc.Element("root").Elements("nodeA"))
{
    if (node.Element("nodeImage") == null)
    {
        cur.Add(node);
    }
    else
    {
        res.Add(cur);
        res.Add(new XElement("root", node));
        cur = new XElement("root");
    }
}
res.Add(cur);

0

这个可行。一定要进行广泛的测试。

var doc = new XmlDocument();
doc.LoadXml(@"<root>
<nodeA>
    Hello
</nodeA>
<nodeA>
    <nodeB>
        node b Text
    </nodeB>
    <nodeImage>
        image.jpg
    </nodeImage>
</nodeA>
<nodeA>
    node a text
</nodeA></root>");

var xmlFrags = new List<string>();
string xml = "<root>";
bool bNewFragment = true;
foreach (XmlNode nodeA in doc.SelectNodes("//root/nodeA")) {
    XmlNode nodeImage = nodeA.SelectSingleNode("nodeImage");
    if (nodeImage != null) {
        xml += "<nodeA>";
        var en = nodeA.GetEnumerator();
        while (en.MoveNext()) {
            XmlNode xn = (XmlNode)en.Current;
            if (xn != nodeImage)
            xml += xn.OuterXml;
        }
        xml += "</nodeA></root>";
        xmlFrags.Add(xml);
        xml = "<root><nodeA>" + nodeImage.OuterXml + "</nodeA></root>";
        xmlFrags.Add(xml);
        bNewFragment = true;
    }
    else 
    {
        if (bNewFragment) {
            xml = "<root>";
            bNewFragment = false;
        }
        xml += nodeA.OuterXml;
    }
}
if (!bNewFragment) {
    xml += "</root>";
    xmlFrags.Add(xml);
}
//Use the XML fragments as you like
foreach (var xmlFrag in xmlFrags)
    Console.WriteLine(xmlFrag + Environment.NewLine);

0

试试这个:

using System;
using System.Xml;

class Program
{
    static void Main(string[] args)
    {
        // create the XML documents
        XmlDocument
            doc1 = new XmlDocument(),
            doc2 = new XmlDocument(),
            doc3 = new XmlDocument();

        // load the initial XMl into doc1
        doc1.Load("input.xml");

        // create the structure of doc2 and doc3
        doc2.AppendChild(doc2.ImportNode(doc1.FirstChild, false));
        doc3.AppendChild(doc3.ImportNode(doc1.FirstChild, false));
        doc2.AppendChild(doc2.ImportNode(doc1.DocumentElement, false));
        doc3.AppendChild(doc3.ImportNode(doc1.DocumentElement, false));

        // select the nodeImage
        var nodeImage = doc1.SelectSingleNode("//nodeImage");
        if (nodeImage != null)
        {
            // append to doc3
            var node3 = nodeImage.ParentNode.NextSibling;
            var n3 = doc3.ImportNode(node3, true);
            doc3.DocumentElement.AppendChild(n3);

            // append to doc2
            var n2 = doc2.ImportNode(nodeImage.ParentNode, true);
            n2.RemoveChild(n2.SelectSingleNode("//nodeImage").PreviousSibling);
            doc2.DocumentElement.AppendChild(n2);

            // remove from doc1
            nodeImage.ParentNode.ParentNode
                .RemoveChild(nodeImage.ParentNode.NextSibling);
            nodeImage.ParentNode
                .RemoveChild(nodeImage);
        }

        Console.WriteLine(doc1.InnerXml);
        Console.WriteLine(doc2.InnerXml);
        Console.WriteLine(doc3.InnerXml);
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接