迭代具有多个子节点的XML文档

时间:2015-10-14 10:02:31

标签: c# xml

我在循环浏览XML文档的节点时遇到了困难。 我有一个具有以下层次结构的文档:

<?xml version="1.0" encoding="UTF-8"?>
<TEMPONDERZOEK xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<TRIES>3</TRIES>
<RESULTATEN>
   <INSTRUMENT>
      <INSTRUMENT_CODE>SPOTCHEM EZ</INSTRUMENT_CODE>
      <TEST_CODE>0</TEST_CODE>
      <VLAG>1</VLAG>
      <ANALYSES>
         <ANALYSE>
            <AFKORTING>BUN</AFKORTING>
            <WAARDE>23.7</WAARDE>
            <EENHEID>MMOL/L</EENHEID>
         </ANALYSE>
         <ANALYSE>
            <AFKORTING>GLU</AFKORTING>
            <WAARDE>15.0</WAARDE>
            <EENHEID>MMOL/L</EENHEID>
         </ANALYSE>
      </ANALYSES>
   </INSTRUMENT>
   <INSTRUMENT>
      <INSTRUMENT_CODE>SPOTCHEM EL</INSTRUMENT_CODE>
      <TEST_CODE>1</TEST_CODE>
      <VLAG>1</VLAG>
      <ANALYSES>
         <ANALYSE>
            <AFKORTING>Na</AFKORTING>
            <WAARDE> 152</WAARDE>
            <EENHEID>mmol/L</EENHEID>
         </ANALYSE>
         <ANALYSE>
            <AFKORTING>K</AFKORTING>
            <WAARDE> 4.4</WAARDE>
            <EENHEID>mmol/L</EENHEID>
         </ANALYSE>
      </ANALYSES>
   </INSTRUMENT>
</RESULTATEN>
</TEMPONDERZOEK>

我编写了以下C#代码来遍历文档:

 // Get all fraudulent XML files
        string[] fraudulentsArray = Directory.GetFiles(@"tempXML\fraudulent", "temp_*.xml");

        // Iterate through every XML file that has been collected
        foreach (var x in fraudulentsArray)
        {
            XmlDocument xml = new XmlDocument();
            xml.Load(x);

            // Get the first parent node
            XmlNode resultaten = xml.SelectSingleNode("//RESULTATEN");

            // Get all the INSTRUMENT nodes in RESULTATEN
            var instrumentNodes = resultaten.SelectNodes("//INSTRUMENT");

            // Loop through the instrument nodes
            for (int i = 0; i < instrumentNodes.Count; i++)
            {
                // Get the values from nodes inside parent node INSTRUMENT and store them
                xmlanalyse.INSTRUMENT_CODE = instrumentNodes[i].ChildNodes[0].InnerText;
                xmlanalyse.TEST_CODE = instrumentNodes[i].ChildNodes[1].InnerText.ToInt();
                xmlanalyse.VLAG = instrumentNodes[i].ChildNodes[2].InnerText.ToInt();

                // Get the ANALYSES parent node
                XmlNode analyses = instrumentNodes[i].SelectSingleNode("//ANALYSES");

                // Get all the ANALYSE nodes in parent node ANALYSES
                var analysesNodes = analyses.SelectNodes("//ANALYSE");

                // Loop through the ANALYSE nodes
                for (int j = 0; j < analysesNodes.Count; j++)
                {
                    // Store them..
                    ANALYSE tempresultaat = new ANALYSE();

                    tempresultaat.AFKORTING = analysesNodes[j].ChildNodes[0].InnerText;
                    tempresultaat.WAARDE = analysesNodes[j].ChildNodes[1].InnerText;
                    tempresultaat.EENHEID = analysesNodes[j].ChildNodes[2].InnerText;

                    xmlanalyse.ANALYSES.Add(tempresultaat);
                }

                onderzoek.RESULTATEN.Add(xmlanalyse);
            }
        }

我对此循环的问题在于它没有区分INSTRUMENT节点。结果是在第一个循环中,我从第一个INSTRUMENT节点获取ANALYZE的所有值,但我也从第二个INSTRUMENT节点获得ANALYZE的值。这也发生在第二个循环中。

1 个答案:

答案 0 :(得分:1)

您需要在XPATH表达式上指明当前上下文(只是.):

var instrumentNodes = resultaten.SelectNodes(".//INSTRUMENT");
var analyses = instrumentNodes[i].SelectSingleNode(".//ANALYSES");
var analysesNodes = analyses.SelectNodes(".//ANALYSE");

理想情况下,您可以删除所有//并使用默认的当前上下文:

foreach (XmlElement instrument in xml.SelectNodes("//INSTRUMENT"))
{
    Console.WriteLine(instrument.SelectSingleNode("INSTRUMENT_CODE").InnerText);

    foreach (XmlElement analyse in instrument.SelectNodes("ANALYSES/ANALYSE"))
    {
        Console.WriteLine(analyse.SelectSingleNode("AFKORTING").InnerText);
    }
}

另一个建议是避免使用ChildNodes[n]语法,因为如果XML文件发生更改,代码将会中断。考虑上面的“AFKORTING”示例。

您是否尝试将XML文件转换为业务对象?你试过deserialize吗?