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

发布于 2024-09-03 20:26:06 字数 697 浏览 8 评论 0原文

我遇到了这样的场景:

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 内容的“快照”而不干扰其位置?

I got this scenario:

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

In the above loop I'm transforming a certain node (itemElementName) into an XElement.

Some nodes will be good XML and will go into an XElement, however, some will not.

In the CATCH, I'd like to not only catch the standard XmlException stuff... I'd also like to catch an extract of the current Xml and a string.

However, if I do any kind of READ operation on the node before I pass it to the XElement, it moves the reader forward.

How can get a "snapshot" of the contents of the OuterXml of the reader without interfering with it's position?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

怕倦 2024-09-10 20:26:06

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

Actually ReadSubtree will return a reader which "wraps" the original reader. So reading through the new one will end up advancing the original one as well.
You must consider XmlReader as a forward only reader, it simply can't go back.
As for your scenario, instead of trying to remember part of the XML you can ask the reader for the position in the input file. Just cast it to IXmlLineInfo interface, it has methods to return line and position. Using this you could remember some starting position (before the element in question) and then the end position of the error. And then read that part from the intput file as a plain text.

难如初 2024-09-10 20:26:06

另一个想法:读取外部 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();
}                  

Another idea: read the outer XML (which advances the reader), then create a new reader from this XML which allows you to "go back" and process the elements of the current node.

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();
}                  
極樂鬼 2024-09-10 20:26:06

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

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

Don't use any 'Read' operation on the reader- as you've discovered, this advances it. Use calls to properties such as reader.HasValue and reader.Value to inspect the contents. Look up 'XmlReader' in the object browser, there's quite a few properties you can read.

Edit: I don't think there's an easy way of simply getting the XML, possibly because the current node may not be valid XML on it's own, such as an XmlWhiteSpace, XmlText node or even an XmlAttribute.

一百个冬季 2024-09-10 20:26:06

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

What I did was read just the element into an XmlDocument, and read that instead. In my case, I had to convert a flow document to HTML. I had to read a inner element to assign a "style" to the parent HTML element.

萌无敌 2024-09-10 20:26:06

事实上,尽管 Vitek Karas MSFT 是正确的,Helena Kupkova 在 https://msdn.microsoft.com/en-us/library/aa302292.aspx。这使得可以使用缓存进行倒退。

In fact, although Vitek Karas MSFT is right, Helena Kupkova published a deft little XML Bookmark Reader on https://msdn.microsoft.com/en-us/library/aa302292.aspx. This enables going backwards using caching.

亣腦蒛氧 2024-09-10 20:26:06

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

Something like that with 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();
                                                }
                                        }
                                    }
                                }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文