gpt4 book ai didi

c# - 如何在不读取的情况下检查 xml 中是否存在另一个节点 - C#

转载 作者:太空宇宙 更新时间:2023-11-03 15:02:54 27 4
gpt4 key购买 nike

我想实现将 xml 反序列化为对象列表的代码。我在 while 向前读取的代码中发现了一个问题,因此跳过了所有其他节点。检查要在此代码的 while 循环中实现的 xml 中的下一个节点的正确方法是什么?

private Task<List<TAxEntity>> Deserialize(XmlReader reader)
{
var deserializer = new XmlSerializer(typeof(TAxEntity));
var entities = new List<TAxEntity>();

do
{
using (var stringReader = new StringReader(reader.ReadOuterXml()))
{
var entity = (TAxEntity)deserializer.Deserialize(stringReader);

entities.Add(entity);
}
}
while (reader.ReadToNextSibling(EntityElementName));

return Task.FromResult(entities);
}

最佳答案

要检查 XmlReader 是否已正确定位,您可以检查是否 reader.NodeType == XmlNodeType.Elementreader.Name == EntityElementName .然后,如果阅读器已经正确定位,则不要使用 ReadToNextSibling() 向前扫描。

但是,您的算法需要做一些改进:

  1. 不是检查正确的 reader.Name,而是检查 LocalName 是否正确。和 NamespaceURI符合预期,如果不符合,请调用 reader.ReadToNextSibling(string localName,string namespaceURI) .这避免了 namespace 前缀的硬编码,即 bug to be avoided .

  2. 调用 reader.ReadSubtree() 而不是 ReadOuterXml()并将返回的读取器直接传递给 deserializer.Deserialize()。您当前的算法解析 XML,将其重新格式化为第二个 XML 字符串,然后再次解析该字符串。使用 ReadSubtree() 允许 XmlSerializer 直接从传入的 XmlReader 流式传输嵌套元素,从而避免这种额外的解析和重新格式化。

将所有这些放在一起,您可以引入以下较低级别的扩展方法:

public static class XmlReaderExtensions
{
public static IEnumerable<TElement> DeserializeSequence<TElement>(this XmlReader reader, string localEntityElementName, string namespaceURI)
{
if (reader == null)
throw new ArgumentNullException();
var deserializer = new XmlSerializer(typeof(TElement));
while ((reader.NodeType == XmlNodeType.Element && reader.LocalName == localEntityElementName && reader.NamespaceURI == namespaceURI)
|| reader.ReadToNextSibling(localEntityElementName, namespaceURI))
{
// Using ReadSubtree instead of ReadOuterXml() avoids having do parse, reformat, then parse the formatted XML a second time
// by reading directly from the current stream only once.
TElement element;
using (var subReader = reader.ReadSubtree())
{
element = (TElement)deserializer.Deserialize(subReader);
}
// Consume the EndElement also (or move past the current element if reader.IsEmptyElement).
reader.Read();
yield return element;
}
}
}

并修改你的Deserialize()方法如下:

    private Task<List<TAxEntity>> Deserialize(XmlReader reader)
{
var entities = reader.DeserializeSequence<TAxEntity>(EntityElementName, "" /* Pass the correct namespace here */).ToList();

return Task.FromResult(entities);
}

样本 .Net fiddle .

请注意,任何手动 XmlReader 代码都应该使用缩进和未缩进的 XML 进行单元测试,因为涉及跳过节点的错误有时会在解析缩进 XML 时被掩盖(因为空白节点被跳过。)

关于c# - 如何在不读取的情况下检查 xml 中是否存在另一个节点 - C#,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45244717/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com