我想通过指定的节点名将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>
我想通过'nodeImage'将这个xml文档拆分为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文档。
答案 0 :(得分:1)
XElement xe = XElement.Load(XMLFile);
foreach(XElement newXE in xe.Elements("nodeA"))
{
XElement root = new XElement("root",newXE);
root.Save(newFile);
}
答案 1 :(得分:1)
“分裂”一词略显混乱。分裂一次不会产生三个部分。
我首先尝试在Linq中将您的问题定义为xml术语。 对于要创建的每个XDocument.Descendants(“nodeImage”):
XDocument的深层副本很容易。它有一个复制构造函数。 当然,如果您的xml具有相当大的规模,那么这对内存来说就是一种痛苦。
但是,挑战在于将节点放在每个副本中。 This question显示了如何获取元素的XPath。你可以使用它。
答案 2 :(得分: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);
答案 3 :(得分: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);
答案 4 :(得分: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);
}
}