繁体   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