簡體   English   中英

在C#XML中解析XML以獲取特定內容

[英]Parsing XML in C# XML for specific Content

我正在嘗試從C#網站解析XML響應。 響應的格式類似於以下內容:

<Company>
    <Owner>Bob</Owner>
    <Contact>
        <address> -1 Infinite Loop </address>
        <phone>
            <LandLine>(000) 555-5555</LandLine>
            <Fax> (000) 555-5556 </Fax>
        </phone>
        <email> foo@bar.com </email>
    </Contact>
</Company>

我唯一需要的信息是座機和傳真號碼。 但是,我當前的方法似乎真的質量很差。 本質上,它是一堆嵌套的while循環,並檢查到Element名稱,然后在找到正確的Element時讀取Content。 我正在使用類似下面的清單:

XmlReader xml = XmlReader.Create(websiteResultStream, xmlSettings);

while(xml.Read()){
    if(xml.NodeType == XmlNodeType.Element){
        if(xml.Name.ToString() == "Phone"){
            while(xml.Read()) {
                if(xml.NodeType == XmlNodeType.Element) {
                     if(xml.Name.ToString() == "LandLine"){
                          xml.MoveToContent();
                          xml.ReadContentAsString();
                     }
                     if(xml.Name.ToString() == "Fax"){
                          xml.MoveToContent();
                          xml.ReadContentAsString();
                     }
                }
            }
        }
    }
}

我是XML / C#的新手,但是上述方法只會尖叫錯誤的代碼! 我想確保如果結構發生變化(例如,還有其他電話號碼類型,例如“手機”),則代碼是可靠的(因此,附加的while循環)

注意:上面的C#代碼不准確,並且缺少一些檢查等,但是它演示了我當前的糟糕透頂方法

從這兩個元素中提取內容的最佳/最干凈的方法是什么?

使用LINQ-to-XML

var doc = XDocument.Parse(@"<Company>
    <Owner>Bob</Owner>
    <Contact>
        <address> -1 Infinite Loop </address>
        <phone>
            <LandLine>(000) 555-5555</LandLine>
            <Fax> (000) 555-5556 </Fax>
        </phone>
        <email> foo@bar.com </email>
    </Contact>
</Company>");

var phone = doc.Root.Element("Contact").Element("phone");

Console.WriteLine((string)phone.Element("LandLine"));
Console.WriteLine((string)phone.Element("Fax"));

輸出:

(000) 555-5555
 (000) 555-5556

對XML文檔中的特定節點進行只讀訪問的最輕量的方法是將XPathDocument和XPath表達式一起使用:

XPathDocument xdoc = new XPathDocument(@"C:\sample\document.xml");
XPathNavigator node = xdoc.CreateNavigator()
    .SelectSingleNode("/Company/Contact/phone/LandLine");
if (node != null)
{
    string landline = node.Value;
}

我認為你離得太遠了。 有更方便的方法(很多不同的方法)。 假設您希望采用與此處相同的基本方法(如果使用冗長的方法,這是一種有效的方法),我將這樣做:

bool inPhone = false;
string landLine = null;
string fax = null;

using(xml = XmlReader.Create(websiteResultStream, xmlSettings)
while(xml.Read())
{
  switch(xml.NodeType)
  {
    case XmlNodeType.Element:
      switch(xml.LocalName)
      {
        case "phone":
          inPhone = true;
          break;
        case "LandLine":
          if(inPhone)
          {
            landLine = xml.ReadElementContentAsString();
            if(fax != null)
            {
              DoWhatWeWantToDoWithTheseValues(landline, fax);
              return;
            }
          }
          break;
        case "Fax":
          if(inPhone)
          {
            fax = xml.ReadElementContentAsString();
            if(landLine != null)
            {
              DoWhatWeWantToDoWithTheseValues(landline, fax);
              return;
            }
          }
          break;
      }
      break;
    case XmlNodeType.EndElement:
      if(xml.LocalName == "phone")
        inPhone = false;
      break;
  }
}

請注意,這將跟蹤它是否在Phone元素內,您將在其中重新檢查以后的元素內的LandLine,這似乎是您要避免的。

還要注意,我們清理了XmlReader,並在獲得所有所需信息后立即返回。

最好的方法是使用XPath。 請參考本文,以供參考: http : //support.microsoft.com/kb/308333

以及本文的操作方法: http : //www.codeproject.com/KB/cpp/myXPath.aspx

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM