16

我正在解析大量大文件,在分析我的瓶颈之后是:

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?
   }
}

我希望能够构建一个List<XmlNode>对象。我在.NET 2.0上。

任何帮助表示赞赏!

4

6 回答 6

18

为什么不只做以下事情?

XmlDocument doc = new XmlDocument();
XmlNode node = doc.ReadNode(reader);
于 2010-04-15T13:38:48.633 回答
7

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);
    }        
}
于 2009-10-14T13:30:25.787 回答
6

XmlReader并且XmlDocument有非常独特的处理方式。XmlReader在内存中不保留任何内容并使用只进的方法,而不是在内存中为XmlDocument. 当性能是一个问题时它很有帮助,但它也需要您以不同的方式编写应用程序:而不是使用XmlNode,您不保留任何东西,只处理“在旅途中”:即,当您需要的元素经过时,你做点什么。这与 SAX 方法很接近,但没有回调模型。

“如何获取 XmlElement”的答案是:您必须根据读者提供的信息从头开始构建它们。不幸的是,这无视了性能提升。切换到 XmlReader 后,通常最好完全避免使用 DOM 方法,除非有一些不同的情况。

SelectNodes此外,此处不能使用使用 XPath 提取节点的“非常方便”的方法(如上所示):XPath 需要 DOM 树。将此方法视为一种过滤方法:您可以将过滤器添加到 XmlReader 并告诉它跳过某些节点或读取直到某个节点。这是非常快的,但思维方式不同。

于 2009-10-14T13:32:17.203 回答
4

用于XmlDocument.ReadNode这种方法。放入XmlReaderusing 语句并使用XmlReader.LocalName而不是 Name 来删除命名空间前缀。

于 2009-10-14T13:46:10.490 回答
1

当我不得不将数据从 aXmlReader插入 a时,我使用了以下解决方法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();
于 2009-11-03T17:45:39.530 回答
1

这是我的方法:

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"})) 
{
    ....
}

然后可以将节点导入另一个文档以进行进一步处理。

于 2011-05-02T08:30:27.363 回答