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

时间:2016-06-16 15:24:13

标签: c# xmlreader xml-attribute

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

<WebError Key="A">
  <Message>B</Message>
  <Parameters>
    <Parameter name="C">D</Parameter>
  </Parameters>
</WebError>

我找不到让XmlReader读取Key属性的方法,以便reader.NodeTypeXmlNodeType.Attributereader.LocalName"Key"

这是我初始化XmlReader

的方法
XmlReader.Create(stream, new XmlReaderSettings { CloseInput = true, IgnoreWhitespace = true });

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

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

首次尝试,通过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
}

很明显,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"
  ...
}

显然,当我拨打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"
  ...
}

这也不起作用。那么,我该如何进入WebError@Key节点?

2 个答案:

答案 0 :(得分:1)

This question(遗憾的是,在&#34; xmlreader c#属性&#34;的搜索结果中没有出现)包含an answer,这让我理解了问题:Read()不要将读者放在属性上。首先移动到元素,然后移动到其内容,然后移动到其属性。只有这个订单有效。

如果您在<{strong> 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)
      }
    }
  }
}

答案 1 :(得分:0)

最简单的方法是使用ReadToFollowingGetAttribute方法。

reader.ReadToFollowing("WebError");
string keyAttr = reader.GetAttribute("Key");