请考虑以下示例XML。我有一个类说Dummy包含两个字段X和Y.通过XML解析我想构建该类的对象列表。 X和Y分别取X和Y标签的值,它们仅在B父节点内。在XML中,X节点和Y节点可能存在于B节点内部,也可能不存在。
<DOC>
<A>1</A>
<B>
<C>1</C>
<D>1</D>
<E>1</E>
<X>Hello</X>
<F>1</F>
<G>1</G>
<Y>Hi</Y>
</B>
<B>
<C>1</C>
<D>1</D>
<E>1</E>
<F>1</F>
<G>1</G>
</B>
<H>
<X>1</X> //ignore
<Y>1</Y> //ignore
</H>
<DOC>
对于上面的XML,我想让列表包含两个元素。第一套将有&#34;嗨&#34;,&#34;你好&#34;另一组将有&#34;&#34;,&#34;&#34;
我的C#解析代码看起来像这样
List<Dummy> dummyList = new List<Dummy>();
Dummy d = null;
while (xmlReader.Read())
{
if (xmlReader.IsStartElement())
{
switch (xmlReader.Name)
{
case "B":
d = new Dummy();
while(xmlReader.Name != "X")
xmlReader.Read(); // can go into infinite loop if there is no X node
xmlReader.Read();
d.X = xmlReader.Value;
while(xmlReader.Name != "Y")
xmlReader.Read(); // can go into infinite loop if there is no Y node
xmlReader.Read();
d.Y = xmlReader.Value;
dummyList.Add(d);
d = null;
break;
}
}
}
上面的代码适用于第一个B节点,但不是第二个B节点。 请让我知道你的想法。
答案 0 :(得分:0)
你的意思是第二个B节点失败了。
正如我在第二个B节点中看到的,你没有任何X或Y.这意味着当它进入内部开关和情况“B”时你开始循环直到它找到不再存在的X.所以它读到最后都没有发生。你必须只读取直到B节点结束(这将确保你无限循环),如果没有X和Y,你必须为它们制作手动空字符串。
答案 1 :(得分:0)
bool waitingForXy = false;
while (xmlReader.Read())
{
if (xmlReader.IsStartElement())
{
switch (xmlReader.Name)
{
case "B":
d = new Dummy();
waitingForXy = true;
break;
case "X":
if (waitingForXy)
{
d.X = xmlReader.ReadString();
}
break;
case "Y":
if (waitingForXy)
{
d.Y = xmlReader.ReadString();
}
break;
}
}
else if (xmlReader.NodeType == XmlNodeType.EndElement)
{
switch (xmlReader.Name)
{
case "B":
waitingForXy = false;
dummyList.Add(d);
break;
}
}
}
这将在每个<B>
开始元素上创建一个虚拟实例,并等待<X>
和<Y>
出现,直到</B>
结束元素。如果它们不存在,d.X
和d.Y
将保持为空。
答案 2 :(得分:0)
如果您使用的是VS2013 SP2或更高版本,则可以使用Edit->Paste Special->Paste XML As Classes
将强类型类复制并粘贴到原始XML的代码中。请注意,您必须关闭最终的</DOC>
并删除评论才能生效!
然后,您可以使用以下代码将XML中任何B的任何X和Y值提取到元组集合中:
string xml = // TODO: Get XML as string.
var myXml = (DOC)new XmlSerializer(typeof(DOC)).Deserialize(new StringReader(xml));
var results = myXml.B.Select(x => Tuple.Create(x.X, x.Y));