如何从XmlReader中读取而不向前移动它

时间:2010-06-01 06:48:11

标签: c# .net xml xml-parsing xmlreader

嘿伙计们,我有这个场景:

while (reader.Read())
{
    if (reader.NodeType == XmlNodeType.Element && reader.Name == itemElementName)
    {
        XElement item = null;
        try
        {
            item = XElement.ReadFrom(reader) as XElement;
        }
        catch (XmlException ex)
        {
           //log line number and stuff from XmlException class  
        }
    }
}

在上面的循环中,我正在将某个节点(itemElementName)转换为XElement。

某些节点将是良好的XML并将进入XElement,但有些节点不会。

在CATCH中,我不仅要捕获标准的XmlException内容......我还想捕获当前Xml和字符串的摘录。

但是,如果我在将节点传递给XElement之前对节点进行任何类型的READ操作,它会向前移动读取器。

如何在不干扰其位置的情况下获取阅读器外部内容的“快照”?

6 个答案:

答案 0 :(得分:10)

实际上,ReadSubtree将返回一个“包装”原始阅读器的阅读器。因此,通过新的阅读将最终推进原始的。 您必须将XmlReader视为仅向前阅读器,它根本无法返回。 至于您的场景,您可以向读者询问输入文件中的位置,而不是尝试记住部分XML。只需将其强制转换为IXmlLineInfo接口,它就有返回行和位置的方法。使用它你可以记住一些起始位置(在有问题的元素之前),然后记住错误的结束位置。然后从intput文件中读取该部分作为纯文本。

答案 1 :(得分:3)

不要在阅读器上使用任何“读取”操作 - 正如您所发现的那样,这可以推进它。使用对reader.HasValuereader.Value等属性的调用来检查内容。在对象浏览器中查找“XmlReader”,您可以阅读很多属性。

编辑:我认为没有一种简单的方法可以简单地获取XML,可能是因为当前节点可能不是它自己的有效XML,例如XmlWhiteSpace,XmlText节点甚至是XmlAttribute。

答案 2 :(得分:1)

另一个想法:阅读外部XML(推进读者),然后从这个XML创建一个新的阅读器,它允许你回过头来#34;并处理当前节点的元素。

while (r.ReadToFollowing("ParentNode"))
{
    parentXml = r.ReadOuterXml();

    //since ReadOuterXml() advances the reader to the next parent node, create a new reader to read the remaining elements of the current parent
    XmlReader r2 = XmlReader.Create(new StringReader(parentXml));
    r2.ReadToFollowing("ChildNode");
    childValue = r2.ReadElementContentAsString();
    r2.Close();
}                  

答案 3 :(得分:1)

我所做的只是将元素读入XmlDocument,然后读取它。就我而言,我必须将流文档转换为HTML。我必须阅读一个内部元素来指定一个"样式"到父HTML元素。

答案 4 :(得分:0)

事实上,虽然Vitek Karas MSFT是对的,但Helena Kupkova在https://msdn.microsoft.com/en-us/library/aa302292.aspx上发布了一个灵巧的小型书签阅读器。这样可以使用缓存向后移动。

答案 5 :(得分:0)

与ReadSubtree类似的东西

using (XmlReader reader = XmlReader.Create(new StringReader(xml)))
                                {
                                    reader.MoveToContent();
                                    while (reader.Read())
                                    {
                                        switch (reader.NodeType)
                                        {
                                            case XmlNodeType.Element:
                                                if (reader.Name == "Field") // for example i need to read node field
                                                {

                                                    XmlReader inner = reader.ReadSubtree();  // the reader stays in the same  position
                                                    XElement El = XElement.Load(inner) as XElement;
                                                    inner.Close();
                                                }
                                        }
                                    }
                                }