使用XmlReader从更大的XML的特定元素创建XDocument

时间:2017-07-26 15:36:13

标签: c# xml linq linq-to-xml

我有一个非常大的XML文件(> 100MB),我想只通过Linq到XML查看其中的一些小元素。

我知道有很多方法可以做到这一点,但是我希望将它保存在内存中,以便在整个程序中的不同位置使用,因此,我想要做的就是遍历此文档一次XMLReader并创建我自己的XDocument变量,其中只包含我需要查看的元素,但我不确定如何正确执行此操作。

这是我到目前为止所用代码的基础知识:

XDocument parsedXml = new XDocument();

using (var rdr = new XmlTextReader(fileName))
{
    rdr.MoveToContent();
    rdr.Read();

    while (rdr.NodeType == XmlNodeType.Element)
    {
        switch (rdr.Name)
        {
            case "Node1":
            case "Node2":
            case "Node3":
                XElement newNode = XElement.Load(rdr.ReadSubtree());
                parsedXml.Add(newNode);
                rdr.Read();
                break;
            default:
                rdr.Skip();
                break;
        }
    }
    rdr.Close();
}

它适用于我添加的第一个元素,但是当我尝试添加任何其他节点时,我收到错误 - This operation would create an incorrectly structured document

实现这个目标的最佳方法是什么?

谢谢!

2 个答案:

答案 0 :(得分:1)

我想出了这个作为我的解决方案 - 如果有更好的方法,请让我知道/发布您的解决方案,但是,如果没有,我希望这有助于其他人....

XDocument parsedXml = new XDocument();
parsedXml.AddFirst(new XElement("root"));

using (var rdr = new XmlTextReader(fileName))
{
    rdr.MoveToContent();
    rdr.Read();

    while (rdr.NodeType == XmlNodeType.Element)
    {
        switch (rdr.Name)
        {
            case "Node1":
            case "Node2":
            case "Node3":
                XElement newNode = XElement.Load(rdr.ReadSubtree());
                parsedXml.Root.Add(newNode);
                rdr.Read();
                break;
            default:
                rdr.Skip();
                break;
        }
    }
    rdr.Close();
}

基本上,创建根节点:

parsedXml.AddFirst(new XElement("root"));

然后专门添加:

parsedXml.Root.Add(newNode);

希望这也有助于其他人!!

答案 1 :(得分:1)

使用Xslt就像:

一样简单
XDocument parsedXml = new XDocument();

using (var xr = XmlReader.Create(fileName))
{
    using (var xw = parsedXml.CreateWriter())
    {
        XslCompiledTransform ct = new XslCompiledTransform();
        ct.Load(xsltFileName);
        ct.Transform(fileName, xw);
    }
}

我尝试进行一些快速分析,但我手边没有合适的Xml源代码,因此您可能需要尝试使用真实数据。

虽然您可能的简化示例肯定不需要复杂的转换,但Xslt可以快速胜过真实世界数据所需的switch-caseif

值得注意的另一件事是使用XmlReader.Create()

中提及的XmlTextReader()而不是{{1}}