2015-10-14 71 views
0

我在循环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

你需要注明您的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吗?