我正在使用XmlReader
遍历一个大型XML文档,并将其拼接成更小,更易于管理的XmlDocmuent
。一路上,我发现一个有趣的节点,所以移动它我这样做:
targetDoc.LoadXml("<result></result>");
// Some interesting code removed
using (XmlReader r = XmlReader.Create(file))
{
while (r.Read())
{
if (r.NodeType == XmlNodeType.Element)
{
if (r.Name == match)
{
// Put the node into the target document
targetDoc.FirstChild.InnerXml = r.ReadOuterXml();
return targetDoc;
}
}
}
}
这一切都很好,除了我想要包含节点而没有它的后代。我感兴趣的是节点本身及其属性。在这一点上,后代非常庞大,笨重且无趣。 (并将它们一次性读入内存会导致内存不足错误......)
是否有一种简单的方法可以将找到的元素的文本(?)及其属性(而不是其后代)放入目标文档中?
答案 0 :(得分:1)
我认为没有内置的方法。我想你必须自己读出属性和内容。
e.g。
static void Main(string[] args)
{
var xml = @"<root>
<parent a1 = 'foo' a2 = 'bar'>Some Parent text
<child a3 = 'frob' a2= 'brob'> Some Child Text
</child>
</parent>
</root>";
var file = new StringReader(xml) ;
using (XmlReader r = XmlReader.Create(file))
{
while (r.Read())
{
if (r.NodeType == XmlNodeType.Element)
{
if (r.Name == "parent")
{
var output = new StringBuilder();
var settings = new XmlWriterSettings();
settings.OmitXmlDeclaration = true;
using (var elementWriter = XmlWriter.Create(output, settings))
{
elementWriter.WriteStartElement(r.Name);
elementWriter.WriteAttributes(r,false);
elementWriter.WriteValue(r.ReadString());
elementWriter.WriteEndElement();
}
Console.WriteLine(output.ToString());
}
}
}
}
if (System.Diagnostics.Debugger.IsAttached)
Console.ReadLine();
}
将产生
<parent a1="foo" a2="bar">Some Parent text</parent>
Press any key to continue . . .
答案 1 :(得分:0)
您可以尝试使用XmlNode.CloneNode(bool deep)方法。
deep:true以递归方式克隆指定节点下的子树; false仅克隆节点本身。
答案 2 :(得分:0)
不一定很好,但是你可以读取字符串,直到你到达开始标记的末尾,然后手动附加一个结束标记并将其加载到XmlDocument中。
编辑:
思考如下:
string xml = r.ReadOuterXml();
int firstEndTag = xml.IndexOf('>');
int lastStartTag = xml.LastIndexOf('<');
string newXml = xml.Substring(0, firstEndTag) + xml.Substring(lastStartTag);
这可能根本没有效果,因为那里有一个大字符串。你的方式可能是最好的。两者都不漂亮,但考虑到你的限制(这并不是说更好的方法不存在),我个人想不出更好的方法。