这是我尝试从XML中读取的第一次,我遇到的问题是将XML文档的所有元素视为相同的NodeType
。
示例XML:
<AFElement>
<Name>InterfaceBuilderTestBreaker01</Name>
<Template></Template>
<PIInterface>ModbusE</PIInterface>
</AFElement>
其中所有元素都被视为NodeType.Element
,但XmlReader
仅将元素PIInterface视为NodeType.Text
而不是元素。
XML应该使用的模式包含PIInterface的定义:
<xs:element name="Name" type="xs:string" />
<xs:element name="Template" type="xs:string" />
<xs:element name="PIInterface" type="xs:string"/>
解析xml并将其读入对象的代码类似于:
while (reader.Read())
{
switch (reader.NodeType)
{
case XmlNodeType.Element:
switch (reader.Name)
{
case "PIInterface":
// move pointer to element value
reader.Read();
item.Interface = reader.Value;
// move pointer to end element
reader.Read();
break;
}
}
}
有没有理由发生这种情况?我已经看到它同时对待它(元素或文本)我认为快速解决方案是在switch
的第一个NodeType.Text
中添加一个案例,但这似乎是错误的,因为它应该总是对待它。
任何帮助总是受到赞赏。
更新: 创建一个简单的解析示例后,我发现测试XML文件和实际XML文件之间没有相同的行为。 XML似乎很相似,但不知何故它们不一样。
使用XML:
<?xml version="1.0" encoding="utf-8"?>
<Element xmlns="http://tempuri.org/ExampleParse.xsd">
<AFElement>
<Name>ExampleParseName01</Name>
<Template>ExampleParseTemplate</Template>
<PIInterface>ModbusE</PIInterface>
<AFElement>
<Name>ExampleParseName06</Name>
<Template>ExampleParseTemplate</Template>
<PIInterface>ModbusE</PIInterface>
<AFElement>
<Name>ExampleParseName07</Name>
<Template>ExampleParseTemplate</Template>
<PIInterface>ModbusE</PIInterface>
<AFElement>
<Name>ExampleParseName08</Name>
<Template>ExampleParseTemplate</Template>
<PIInterface>ModbusE</PIInterface>
</AFElement>
</AFElement>
</AFElement>
</AFElement>
<AFElement>
<Name>ExampleParseName02</Name>
<Template>ExampleParseTemplate</Template>
<PIInterface>ModbusE</PIInterface>
</AFElement>
</Element>
非工作XML:
<Element xmlns="http://tempuri.org/ExampleParse.xsd">
<AFElement>
<Name>InterfaceBuilderTestBreaker01</Name>
<Template></Template>
<PIInterface>ModbusE</PIInterface>
<AllAttributes>
<AFAttribute name="classic">
<field name="ptclassname" value="ModbusE"/>
<field name="pointsource" value="InterfaceBuilder01"/>
<field name="instrumenttag" value="192.168.1.100"/>
</AFAttribute>
</AllAttributes>
<AFElement>
<Name>InterfaceBuilderTestBreaker02</Name>
<Template></Template>
<PIInterface>ModbusE</PIInterface>
<AllAttributes>
<AFAttribute name="classic">
<field name="ptclassname" value="ModbusE"/>
<field name="pointsource" value="InterfaceBuilder01"/>
<field name="location1" value="1"/>
<field name="location2" value="2"/>
<field name="location3" value=""/>
<field name="location4" value="2"/>
<field name="location5" value=""/>
<field name="instrumenttag" value="192.168.1.100"/>
</AFAttribute>
</AllAttributes>
</AFElement>
<AFElement>
<Name>InterfaceBuilderTestBreaker03</Name>
<Template></Template>
<PIInterface>ModbusE</PIInterface>
<AllAttributes>
<AFAttribute name="classic">
<field name="ptclassname" value="ModbusE"/>
<field name="pointsource" value="InterfaceBuilder01"/>
<field name="location1" value="1"/>
<field name="location2" value="3"/>
<field name="location3" value=""/>
<field name="location4" value="3"/>
<field name="instrumenttag" value="192.168.1.100"/>
</AFAttribute>
</AllAttributes>
</AFElement>
<AFElement>
<Name>InterfaceBuilderTestMeter01</Name>
<Template></Template>
<PIInterface>ModbusE</PIInterface>
<AllAttributes>
<AFAttribute name="classic">
<field name="ptclassname" value="ModbusE"/>
<field name="pointsource" value="InterfaceBuilder02"/>
<field name="instrumenttag" value="192.168.1.101"/>
<field name="exdesc" value=""/>
</AFAttribute>
</AllAttributes>
</AFElement>
</AFElement>
</Element>
我不会认为<AllAttributes>
的元素会导致<PIInterface>
元素被区别对待。其他差异是从Excel中的单元格中的脚本生成的非工作XML以及我手工放在一起的测试元素。我认为输出中没有任何差异可以解释各种处理或元素。
我错过了什么吗?
注意:XML是元素的层次结构,在解析时应该返回删除层次结构的每个元素的列表。正是出于这个原因,我深入研究了低级接口。我愿意重写解析函数以使用不同的接口,但直到现在它仍按预期工作。
更新2: 根据keshlam的评论,一个完整的示例代码块:
private static void internalParser(XmlReader reader, ref int c, ref ObservableCollection<DataHolder> List)
{
DataHolder data = new DataHolder();
data.Title = "Interface" + c;
c++;
while (reader.Read())
{
switch (reader.NodeType)
{
case XmlNodeType.Element:
switch (reader.Name)
{
case "Name":
// move pointer to element value
reader.Read();
data.InterfaceName = reader.Value;
// move pointer to end element
reader.Read();
break;
case "Template":
// move pointer to element value
reader.Read();
data.ElementTemplate = reader.Value;
// move pointer to end element
reader.Read();
break;
case "PIInterface":
// move pointer to element value
reader.Read();
data.ElementInterface = reader.Value;
// move pointer to end element
reader.Read();
break;
case "AFElement":
// create new object for processing
internalParser(reader, ref c, ref List);
break;
}
break;
case XmlNodeType.EndElement:
if (reader.Name == "AFElement")
{
List.Add(data) ;
return ;
}
break;
}
}
return ;
}