我阅读了有关此方法的mdsn文档,但我无法弄清楚以下行为的原因:
假设有这个xml:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<project>
<caseInformation Name="1">
<field >aaaaaaa</field>
<field >bvbbbb</field>
<field >cccc</field>
<field >ddddd</field>
</caseInformation>
</project>
现在,如果您运行以下代码:
while (reader.Read())
{
if (reader.NodeType == XmlNodeType.Element)
{
var name = reader.Name;
if(name == "caseInformation")
{
using (var innerReader = reader.ReadSubtree())
{
while (innerReader.ReadToFollowing("field"))
{
var element = (XElement)XNode.ReadFrom(innerReader);
element.Dump();
}
}
}
}
}
这将产生以下输出:
<field>aaaaaaa</field>
<field>bvbbbb</field>
<field>cccc</field>
<field>ddddd</field>
如果我改变了使用此指令获取元素的方式
var element = (XElement)XNode.ReadFrom(reader);
我得到相同的输出。但我无法理解为什么。
在msdn上声明
ReadSubTree()返回一个新的XmlReader实例,该实例可用于读取当前节点及其所有后代。
那个
关闭新的XML阅读器后,原始阅读器位于子树的EndElement节点上
所以这意味着实际上当我移动innerReader时原始阅读器也会移动?
答案 0 :(得分:2)
实际上,由ReadSubtree()方法返回的新XmlReader并不是真正的新XmlReader,而是源XmlReader上的包装器。
您可以在sourcecode框架中看到它:
public virtual XmlReader ReadSubtree() {
if (NodeType != XmlNodeType.Element) {
throw new InvalidOperationException(Res.GetString(Res.Xml_ReadSubtreeNotOnElement));
}
return new XmlSubtreeReader(this);
}
此XmlSubtreeReader
继承自XmlWrappingReader
。
如果您看到构造函数:
internal XmlWrappingReader( XmlReader baseReader ) {
Debug.Assert( baseReader != null );
this.reader = baseReader;
this.readerAsIXmlLineInfo = baseReader as IXmlLineInfo;
}
所以这意味着实际上当我移动innerReader时 原始读者的举动?
无论如何,这都不成问题,因为在关闭“ subReader”之前,您不应该在原始阅读器上调用方法,否则会出现异常。
根据您的示例代码对该方法的示例用法:
public void ReadProjectInfo()
{
//...
while (reader.Read())
{
if (reader.NodeType == XmlNodeType.Element)
{
if (reader.Name == "caseInformation")
{
ReadCaseInformation(reader.ReadSubtree());
}
}
}
}
public void ReadCaseInformation(XmlReader reader)
{
try
{
// if something raise an exception here
// the main reader is not really affected by that
// because when the methods ends, the "subReader" is closed
// and then the main reader is set on the closing tag.
// so the main XML reader can continue to analyze the xml stream
}
catch (Exception)
{
//...
}
}
希望这会有所帮助
答案 1 :(得分:0)
替换:
var element = (XElement)XNode.ReadFrom(innerReader);
致:
var element = innerReader.ReadElementContentAsString();
输出:
aaaaaaa
bvbbbb
cccc
ddddd