C# 如何在不向前移动的情况下读取XmlReader?

C# 如何在不向前移动的情况下读取XmlReader?,c#,.net,xml,xml-parsing,xmlreader,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; }

我得到了这个场景:

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中,我不仅希望捕获标准的xmleexception内容。。。我还想获取当前Xml和字符串的摘录

但是,如果在将节点传递给XElement之前对其执行任何类型的读取操作,则会将读取器向前移动


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

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


编辑:我认为没有简单的方法获取XML,可能是因为当前节点本身可能不是有效的XML,例如XmlWhiteSpace、XmlText节点甚至XmlAttribute。

实际上ReadSubtree将返回一个“包装”原始读卡器的读卡器。因此,通读新版本最终也会推进原有版本。 您必须将XMLader视为只转发的阅读器,它根本无法返回。
对于您的场景,您可以向读者询问输入文件中的位置,而不是试图记住XML的一部分。只要将它转换到IXmlLineInfo接口,它就有返回行和位置的方法。使用它,您可以记住一些起始位置(在所讨论的元素之前),然后是错误的结束位置。然后以纯文本形式从输入文件中读取该部分。

事实上,尽管Vitek Karas MSFT是正确的,但Helena Kupkova在其上发布了一款灵巧的小型XML书签阅读器。这使得可以使用缓存进行反向操作。

另一个想法是:读取外部XML(这会提升读取器),然后从该XML创建一个新读取器,它允许您“返回”并处理当前节点的元素

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();
}                  

我所做的只是将元素读入一个XmlDocument,然后读取它。在我的例子中,我必须将流文档转换为HTML。我必须读取一个内部元素才能为父HTML元素指定一个“样式”。

类似于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();
                                                }
                                        }
                                    }
                                }

谢谢弗林。。。因此,出于我的目的,我希望在尝试创建XElement时抛出错误之前提取无效xml。你是说那是不可能的吗?可能不是不可能的;我很后悔以前没有记住这一点,但如果调用
reader.ReadSubtree()
,它会创建一个全新的XmlReader,从
reader
所在的位置开始;您可以随意阅读,而不会影响原始的
阅读器
。不是100%确定你会如何在你的情况下使用它,但它看起来可能是一种方式。是的,很好,谢谢你,这正是发生的事情。谢谢你的解释!啊。。我当时完全误解了ReadSubTree的观点。。很抱歉。老实说,虽然从object browser的文档中看不出这一点,但MSDN页面让它更清晰了;在子树完成后,它实际上会完全停止阅读,因此我从未注意到它也提升了原始读取器。这对我来说非常有效,尽管我为StringReader和XmlReader添加了“使用”块。嗨,stef,感谢您回答StackExchange上的问题!虽然这段代码可以回答这个问题,但提供关于它如何和/或为什么解决问题的附加上下文将提高答案的长期价值。另见: