XmlReader最佳实践
本文关键字:最佳 XmlReader | 更新日期: 2023-09-27 18:07:04
我已经很好地阅读了MSDN和关于StackOverflow的XmlReader相关问题,但我还没有遇到一个像样的"最佳实践"示例。
我尝试过各种组合,每种组合似乎都有缺点,但我能想到的最好的组合如下:
XML:<properties>
<actions:name>start</actions:name>
<actions:value type="System.DateTime">06/08/2011 01:26:49</actions:value>
</properties>
代码:
// Reads past the initial/root element
reader.ReadStartElement();
// Check we haven't hit the end
while (!reader.EOF && reader.NodeType != XmlNodeType.EndElement) {
if (reader.IsStartElement("name", NamespaceUri)) {
// Read the name element
this.name = reader.ReadElementContentAsString();
} else if (reader.IsStartElement("value", NamespaceUri)) {
// Read the value element
string valueTypeName = reader["type"] ?? typeof(string).Name;
Type valueType = Type.GetType(valueTypeName);
string valueString = reader.ReadElementContentAsString();
// Other stuff here that doesn;t matter to the XML parsing
} else {
// We can't do anything with this node so skip over it
reader.Read();
}
}
这是从。readsubtree()调用传递到我的类的,每个类读取自己的信息。我希望它不要依赖于特定的顺序。
在此之前,我确实尝试了一些变化。
1) while(reader.Read())
这是从各种例子中得到的,但发现它"遗漏"了一些元素,当元素1的.ReadContent*()
把它留在元素2的开始,.Read
读到元素3。
2)移除.Read()
导致它在我读取的第一个元素后卡住。
3)其他几个我长期认为"失败"的。
就我所见,我所决定的代码似乎是最容易接受和稳定的,但是有什么明显的我错过了吗?
(注意c# 2.0标签,所以LINQ/XNode/XElement不是选项)
一种方法是使用自定义XmlReader。XmlReader是抽象的,可以链接XmlReader,从而提供了一种强大的机制,可以在阅读器中执行一些特定于域的处理。
例子:XamlXmlReader
关于XmlWrappingReader的帮助
下面是如何实现它的示例(参见内联注释):
/// <summary>
/// Depending on the complexity of the Xml structure, a complex statemachine could be required here.
/// Such a reader nicely separates the structure of the Xml from the business logic dependent on the data in the Xml.
/// </summary>
public class CustomXmlReader: XmlWrappingReader
{
public CustomXmlReader(XmlReader xmlReader)
:base(XmlReader.Create(xmlReader, xmlReader.Settings))
{
}
public override bool Read()
{
var b = base.Read();
if (!b)
return false;
_myEnum = MyEnum.None;
if("name".Equals(this.Name))
{
_myEnum = MyEnum.Name;
//custom logic to read the entire element and set the enum, name and any other properties relevant to your domain
//Use base.Read() until you've read the complete "logical" chunk of Xml. The "logical" chunk could be more than a element.
}
if("value".Equals(this.Value))
{
_myEnum = Xml.MyEnum.Value;
//custom logic to read the entire element and set the enum, value and and any other properties relevant to your domain
//Use base.Read() until you've read the complete "logical" chunk of Xml. The "logical" chunk could be more than a element.
}
return true;
}
//These properties could return some domain specific values
#region domain specific reader properties.
private MyEnum _myEnum;
public MyEnum MyEnum
{
get { return _myEnum; }
}
#endregion
}
public enum MyEnum
{
Name,
Value,
None
}
public class MyBusinessAppClass
{
public void DoSomething(XmlReader passedInReader)
{
var myReader = new CustomXmlReader(passedInReader);
while(myReader.Read())
{
switch(myReader.MyEnum)
{
case MyEnum.Name:
//Do something here;
break;
case MyEnum.Value:
//Do something here;
break;
}
}
}
}
提醒一句:对于您在这里展示的一些简单的Xml处理,这可能是过度工程。除非您有两个以上的元素需要自定义处理,否则不建议使用这种方法。