2009-10-14 55 views
13

我解析的大文件的一个大数目和剖析我的瓶颈之后建立将XMLNode是:如何从XmlReader中

XmlDocument doc = new XmlDocument(); 
doc.Load(filename); 

这种做法是非常方便的,因为我可以提取这样的节点:

XmlNodeList nodeList = doc.SelectNodes("myXPath"); 

我切换到XmlReader中,但是当我发现i的元素需要提取我坚持关于如何建立从它的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

任何帮助表示赞赏!

回答

6

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); 
    }   
} 
+1

它似乎在创建空节点? – JohnIdol 2009-10-14 13:59:17

+0

是的,除非您向元素添加任何内容(例如,通过将内容分配给“InnerText”属性),它们将是空的。 – 2009-10-14 14:02:26

+0

oh yep - 现在看起来很明显,因为我只是传入元素名称,谢谢 – JohnIdol 2009-10-14 14:08:22

5

XmlReaderXmlDocument有处理的一个非常独特的方式。 XmlReader在内存中没有任何内容,并且使用只向前方法而不是在内存中为XmlDocument构建完整的DOM树。当性能问题很有帮助时,但它也需要您以不同的方式编写应用程序:而不是使用XmlNode,不保留任何内容,只处理“随时随地”:即当某个元素经过时需要,你做了些什么。这与SAX方法非常接近,但没有回调模型。

“如何获取XmlElement”的答案是:您必须根据读者的信息从头开始构建它们。不幸的是,这不利于性能增益。一旦切换到XmlReader,通常会更好地防止使用DOM方法,除非是少数情况。

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

4

使用此方法的XmlDocument.ReadNode。将XmlReader放在使用语句中,并使用XmlReader.LocalName而不是名称来删除名称空间前缀。

1

我用以下解决方法时,我已经插入来自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(); 
12

为什么不执行以下操作?

XmlDocument doc = new XmlDocument(); 
XmlNode node = doc.ReadNode(reader); 
+0

已经回答。请参阅http://stackoverflow.com/questions/1566192/how-to-build-xmlnodes-from-xmlreader/1566333#1566333。 – 2010-04-15 14:04:18

+0

这是正确的答案,因为另一个留下空白节点! – 2014-03-14 12:45:25

0

这里是我的方法:然后

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

节点可以导入到另一个文档中作进一步处理。