节点可能存在也可能不存在时的XML解析

时间:2016-01-13 12:21:28

标签: c# xml

请考虑以下示例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节点。 请让我知道你的想法。

3 个答案:

答案 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.Xd.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));