【问题标题】:Using .net, XmlReader "look ahead"?使用.net,XmlReader“向前看”?
【发布时间】:2021-03-01 22:04:12
【问题描述】:

我正在修改现有的 VB.NET 代码,我希望尽可能少地更改它,因为它可以工作。

它当前读取的 XML 结构类似于;

<?xml version="1.0" encoding="utf-8"?>
<RootNode>
    <ParentNode>
        <Item ID="A">value</Item>
        <Item ID="B">value</Item>
        <Item ID="C">value</Item>
        <ChildNode>
            <Item ID="CX">value</Item>
            <Item ID="CY">value</Item>
            <Item ID="CZ">value</Item>
            <Item ID="CN">value</Item>
        </ChildNode>
        <ChildNode>
            <Item ID="CX">value</Item>
            <Item ID="CY">value</Item>
            <Item ID="CZ">value</Item>
            <Item ID="CN">value</Item>
        </ChildNode>
    </ParentNode>
<RootNode>

现有代码使用 XMLReader 循环数据。有时,单个文件中的数据将包含数百兆字节,因此一次加载整个 XML 将是一个问题。虽然我的示例只显示了几个项目,但实际上每个子节点中可能有 100 多个项目。

当程序处理数据时,当它到达 ChildNode 时,它​​需要能够从 检索值以处理该特定子节点中的所有其他项目。

我不是 XML 专家,我很茫然。到目前为止,我所阅读的内容表明 XMLReader 是一种无法返回的单向阅读器。

编辑:

使用伪代码当前代码所做的是;

sub processChildNode
    While true
        Read XML
        If in ChildNode then
            doProcessChildNodeItem
        else
            exit while
    end while

    sub doProcessChildNodeItem
        do stuff with current item
    end sub
end sub

我希望它做的是;

sub processChildNode
    tester = getChildNodeCNValue()
    While true
        Read XML
        If in ChildNode then
            doProcessChildNodeItem(tester)
        else
            exit while
        end if
    end while

    sub doProcessChildNodeItem(tester)
        do stuff with current item
        if tester = "myvalue" then
            Do other stuff with current item
        end if
    end sub
end sub

【问题讨论】:

    标签: .net xml


    【解决方案1】:

    要将内存保持在最低限度,请使用 XmlReader(就像您已经在使用的那样)。
    使用 XmlDocument(或类似的)来存储您的匹配项(ChildNode 和关联的 Item 元素)。如果您的匹配结果对于基于 DOM 的结构(约 100k 个元素)来说不是太大,这将起作用

    这里是 C# 代码,转换成 VB 应该不难。

        try {
            string strFileName = HttpContext.Current.Server.MapPath("t.xml");
            XmlReader xmlReader = XmlReader.Create(strFileName);
    
            // Create an XmlDocument just to hold the matches.
            XmlDocument xml = new XmlDocument();
            xml.LoadXml("<xml/>");
    
            while( xmlReader.Read()) {
                if (xmlReader.NodeType == XmlNodeType.Element) {
                    switch (xmlReader.Name.ToString()) {
                        case "ChildNode":
                            XmlNode ndMatchingChildNode = xml.ReadNode(xmlReader);
                            xml.DocumentElement.AppendChild(ndMatchingChildNode);
                            break;
                    }
                }
            }
    
            // Now loop the matching subset
            System.Text.StringBuilder sb = new System.Text.StringBuilder();
            sb.Append("<table>");
            foreach (XmlElement ndMatch in xml.SelectNodes("//ChildNode/Item")) {
                sb.Append("<tr>");
                sb.Append("<td>" + ndMatch.GetAttribute("ID") + "</td>");
                sb.Append("<td>" + ndMatch.InnerText + "</td>");
                sb.Append("<tr>");
            }
            sb.Append("</table>");
            Response.Write(sb.ToString());
    
        } catch( Exception ex ) {
            Response.Write(ex.Message);
        }
    

    【讨论】:

    • 我相信你的建议是通过读取 XML 来构建一个单独的 XML 结构,完成后使用单独的 XML 结构来做任何我想做的事情。我想在构建单独的 XML 结构时,我可以提取后续处理单独的 XML 结构所需的值。
    • 没错,使用 XmlReader 读取您非常大的文件,并将匹配的节点放入您可以使用常规 XPath 抓取的 XmlDocument DOM 文档中。
    猜你喜欢
    • 2012-02-19
    • 2011-01-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-07
    • 2011-02-26
    • 2011-07-15
    • 1970-01-01
    相关资源
    最近更新 更多