C# 如何从XmlReader构建XmlNodes
我正在分析大量的大文件,在分析之后,我的瓶颈是:C# 如何从XmlReader构建XmlNodes,c#,xml,.net-2.0,xmlreader,C#,Xml,.net 2.0,Xmlreader,我正在分析大量的大文件,在分析之后,我的瓶颈是: XmlDocument doc = new XmlDocument(); doc.Load(filename); 这种方法非常方便,因为我可以提取如下节点: XmlNodeList nodeList = doc.SelectNodes("myXPath"); 我正在切换到XmlReader,但当我找到需要提取的元素时,我一直在考虑如何从中构建XmlNode,因为我对XmlReader不太熟悉: XmlReader xmlReader = Xm
XmlDocument doc = new XmlDocument();
doc.Load(filename);
这种方法非常方便,因为我可以提取如下节点:
XmlNodeList nodeList = doc.SelectNodes("myXPath");
我正在切换到XmlReader,但当我找到需要提取的元素时,我一直在考虑如何从中构建XmlNode,因为我对XmlReader不太熟悉:
XmlReader xmlReader = XmlReader.Create(fileName);
while (xmlReader.Read())
{
//keep reading until we see my element
if (xmlReader.Name.Equals("myElementName") && (xmlReader.NodeType == XmlNodeType.Element))
{
// How do I get the Xml element from the reader here?
}
}
我希望能够构建一个列表
对象。我在.NET2.0上
感谢您的帮助 XmlNode类型没有公共构造函数,因此您不能自己创建它们。您需要有一个
XmlDocument
,可以用来创建它们:
XmlDocument doc = new XmlDocument();
while (xmlReader.Read())
{
//keep reading until we see my element
if (xmlReader.Name.Equals("myElementName") && (xmlReader.NodeType == XmlNodeType.Element))
{
// How do I get the Xml element from the reader here?
XmlNode myNode = doc.CreateNode(XmlNodeType.Element, xmlReader.Name, "");
nodeList.Add(myNode);
}
}
XmlReader
和XmlDocument
具有非常独特的处理方式XmlReader
在内存中不保留任何内容,并使用仅向前的方法,而不是在内存中为XmlDocument
构建完整的DOM树。当性能是一个问题时,它很有帮助,但它也要求您以不同的方式编写应用程序:不使用XmlNode
,您不保留任何内容,只“在运行中”处理:即,当需要的元素经过时,您可以做一些事情。这接近于SAX方法,但没有回调模型
“如何获取XmlElement”的答案是:您必须根据读者提供的信息从头开始构建它们。不幸的是,这与性能增益背道而驰。一旦切换到XmlReader,通常最好不要完全使用DOM方法,除非有一些不同的情况
此外,这里不能使用使用XPath提取节点的“非常方便”的方法(
SelectNodes
就是您上面展示的方法):XPath需要DOM树。将此方法视为一种过滤方法:您可以向XMLRe读器添加筛选器,并告诉它跳过某些节点或读取到某个节点。这非常快,但思维方式不同。使用XmlDocument.ReadNode
进行此方法。将XmlReader
放入using语句中,并使用XmlReader.LocalName
而不是Name来删除命名空间前缀。当我不得不将XmlReader
中的数据插入XmlDocumenht
时,我使用了以下解决方法:
XmlReader rdr = cmd.ExecuteXmlReader();
XmlDocument doc = new XmlDocument();
// create a container node for our resultset
XmlElement root = doc.CreateElement("QueryRoot");
doc.AppendChild(root);
StringBuilder xmlBody = new StringBuilder();
while(rdr.Read())
{
xmlBody.Append(rdr.ReadOuterXml());
}
root.InnerXml = xmlBody.ToString();
为什么不做下面的事情呢
XmlDocument doc = new XmlDocument();
XmlNode node = doc.ReadNode(reader);
我的做法如下:
public static IEnumerable<XmlNode> StreamNodes(
string path,
string[] tagNames)
{
var doc = new XmlDocument();
using (XmlReader xr = XmlReader.Create(path))
{
xr.MoveToContent();
while (true) {
if (xr.NodeType == XmlNodeType.Element &&
tagNames.Contains(xr.Name))
{
var node = doc.ReadNode(xr);
yield return node;
}
else
{
if (!xr.Read())
{
break;
}
}
}
xr.Close();
}
}
// Used like this:
foreach (var el in StreamNodes("orders.xml", new string[]{"order"}))
{
....
}
公共静态IEnumerable StreamNodes(
字符串路径,
字符串[]标记名)
{
var doc=新的XmlDocument();
使用(XmlReader xr=XmlReader.Create(path))
{
xr.MoveToContent();
while(true){
if(xr.NodeType==XmlNodeType.Element&&
标记名.Contains(xr.Name))
{
var node=doc.ReadNode(xr);
收益回报节点;
}
其他的
{
如果(!xr.Read())
{
打破
}
}
}
xr.Close();
}
}
//这样使用:
foreach(StreamNodes中的var el(“orders.xml”,新字符串[]{“order”}))
{
....
}
然后可以将节点导入到另一个文档中进行进一步处理。它似乎正在创建空节点?是的,除非您向元素添加任何内容(例如,通过为
InnerText
属性指定内容),否则它们将为空。哦,是的-现在看起来很明显,因为我刚刚传入元素名称,谢天谢地,这只会导致空节点。您可以使用doc.ReadNode(reader)
实际获取整个节点,因为XmlNode
已经应答。请参阅。这是正确的答案,因为另一个节点为空!