13

我得到了这个场景:

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 操作,它会向前移动阅读器。

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

4

6 回答 6

11

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

于 2010-06-18T22:40:10.413 回答
5

另一个想法:读取外部 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();
}                  
于 2015-07-17T16:56:54.630 回答
4

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

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

于 2010-06-01T08:19:52.243 回答
1

我所做的只是将元素读入 XmlDocument,然后改为读取。就我而言,我必须将流文档转换为 HTML。我必须阅读内部元素才能为父 HTML 元素分配“样式”。

于 2016-09-12T06:50:45.817 回答
0

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

于 2015-01-22T11:39:14.510 回答
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();
                                                }
                                        }
                                    }
                                }
于 2020-06-16T09:17:48.900 回答