如何让 XmlReader 读取 C# 中的属性?

LWC*_*ris 3 c# xmlreader xml-attribute

我有一个包含以下 XML 内容的 XML-Stream:

<WebError Key="A">
  <Message>B</Message>
  <Parameters>
    <Parameter name="C">D</Parameter>
  </Parameters>
</WebError>
Run Code Online (Sandbox Code Playgroud)

我找不到XmlReader读取Key属性的方法,所以reader.NodeTypeisXmlNodeType.Attributereader.LocalNameis "Key"

这就是我初始化我的方式XmlReader

XmlReader.Create(stream, new XmlReaderSettings { CloseInput = true, IgnoreWhitespace = true });
Run Code Online (Sandbox Code Playgroud)

这个读取器然后通过几个方法级别,直到它到达我的解析器函数。

这是我试图让读者阅读该元素的所有替代代码。从代码中剥离了控制结构,因此您只能看到实际调用的函数。

第一次尝试,通过MoveToFirstAttribute()调用移动到属性:

reader.Read(); // true
reader.IsStartElement("WebError"); // true
using (var nodeReader = reader.ReadSubtree()) {
  nodeReader.HasAttributes; // true
  nodeReader.MoveToFirstAttribute(); // false
  nodeReader.Read(); // true
  nodeReader.NodeType; // XmlNodeType.Element
  nodeReader.LocalName; // "WebError"
  using (var subLevelReader = nodeReader.ReadSubtree()) {
  }
  nodeReader.Read(); // false
}
Run Code Online (Sandbox Code Playgroud)

所以很明显,MoveToFirstAttribute并没有打动读者。作为subLevelReader通常用于解析内部XmlElement节点的副作用,现在抓取整个WebError节点,并且在subLevelReader处理时,整个WebError节点被跨过。

第二次尝试,调用MoveToContent()并搜索属性:

reader.Read(); // true
reader.IsStartElement("WebError"); // true
using (var nodeReader = reader.ReadSubtree()) {
  nodeReader.MoveToContent(); // XmlNodeType.Element
  nodeReader.LocalName; // "WebError"
  nodeReader.Read(); // true
  nodeReader.NodeType; // XmlNodeType.Element
  nodeReader.LocalName; // "Message"
  ...
}
Run Code Online (Sandbox Code Playgroud)

显然,当我打电话时,我已经进步得太多了,MoveToContent()因为它移到了WebError起始标签的末尾。

第三次尝试,在调用之前读取属性MoveToContent()

reader.Read(); // true
reader.IsStartElement("WebError"); // true
using (var nodeReader = reader.ReadSubtree()) {
  nodeReader.MoveToAttribute("Key"); // false
  nodeReader.MoveToContent(); // XmlNodeType.Element
  nodeReader.LocalName; // "WebError"
  nodeReader.Read(); // true
  nodeReader.NodeType; // XmlNodeType.Element
  nodeReader.LocalName; // "Message"
  ...
}
Run Code Online (Sandbox Code Playgroud)

这也不起作用。那么,我如何到达WebError@Key节点?

LWC*_*ris 8

这个问题(不幸的是没有出现在“xmlreader c# 属性”的搜索结果中)包含一个让我理解这个问题的答案Read()不会将阅读器定位在一个属性上。首先移至元素,然后移至其内容,然后移至其属性。只有这个顺序有效。

事实证明,如果您之前调用,我的所有方法都有效,但还没有,因为它会读取节点。MoveToContent() MoveToAttribute("Key")MoveToNextAttribute()MoveToFirstAttribute()Read()Message

所以这是实际的代码:

while (reader.Read()) {
  if (!reader.IsStartElement("WebError")) { continue; }

  // We found the WebError node
  using (var nodeReader = reader.ReadSubtree()) {
    nodeReader.MoveToContent();

    // Read the attributes
    while (nodeReader.MoveToNextAttribute()) {
      var nodeName = nodeReader.LocalName;
      if (nodeName == "Key") {
        m_Key = nodeReader.Value; // "A"
        break;
      }
    }

    // Read the XML sub nodes
    while (nodeReader.Read()) {
      if (nodeReader.NodeType != XmlNodeType.Element) { continue; }

      using (var subLevelReader = nodeReader.ReadSubtree()) {
        // Parse sub levels of XML (Message, Parameters)
      }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)