【发布时间】:2017-07-08 12:22:01
【问题描述】:
在尝试最小化 XML 解析程序的内存占用,特别是避免使用 XElement.Load() 加载数百兆字节时,我遇到了建议使用较旧的 XmlReader e.g. here 的文章。
我需要在内部将每个主要元素重构为 XElement 以避免重大重构。但是,我发现如果我的源元素直接相邻,这种方法会跳过每个第二个元素。
我已经解决了这个单元测试的问题(MSTest2 with FluentAssertions):
[DataTestMethod]
[DataRow("<data><entry>1</entry><entry>2</entry><entry>3</entry><entry>4</entry></data>")]
[DataRow("<data><entry>1</entry> <entry>2</entry> <entry>3</entry> <entry>4</entry></data>")]
public void XmlReaderCount(string input)
{
var sr = new StringReader(input);
var xml = XmlReader.Create(sr);
xml.MoveToContent();
var data = new List<string>();
while (xml.Read())
{
if (xml.LocalName == "entry" && xml.NodeType == XmlNodeType.Element)
{
var element = (XElement)System.Xml.Linq.XNode.ReadFrom(xml);
data.Add(element.Value);
}
}
data.Should()
.HaveCount(4);
}
第一个(数据驱动的)测试失败:
预期的集合包含 4 个项目,但找到了 2 个。
因为它将 1 和 3 放入数据收集中。它确实循环了 4 次,但每个其他元素都有一个 xml.NodeType 或 Text,而不是 Element。第二个测试(</entry> 和 <entry> 之间的空格通过处理所有 4 个。
在我的真实示例中,我不能轻易更改源。我已经有了一个受another StackOverflow question 启发的解决方案,所以我可以执行以下操作,但这似乎很奇怪 - 有什么问题吗?
[DataTestMethod]
[DataRow("<data><entry>1</entry><entry>2</entry><entry>3</entry><entry>4</entry></data>")]
[DataRow("<data><entry>1</entry> <entry>2</entry> <entry>3</entry> <entry>4</entry></data>")]
public void XmlReaderCountSubtree(string input)
{
var data = new List<string>();
var sr = new StringReader(input);
var xml = XmlReader.Create(sr);
xml.MoveToContent();
while (xml.Read())
{
if (xml.LocalName == "entry" && xml.NodeType == XmlNodeType.Element)
{
using (var subtree = xml.ReadSubtree())
{
subtree.MoveToContent();
var content = subtree.ReadOuterXml();
var element = XElement.Parse(content);
data.Add(element.Value);
}
}
}
data.Should()
.HaveCount(4);
}
【问题讨论】:
标签: c# xml-parsing