用C#XML解析特定内容的XML

用C#XML解析特定内容的XML,c#,.net,xml,C#,.net,Xml,我正试图用C#解析来自网站的XML响应。响应的格式类似于以下内容: <Company> <Owner>Bob</Owner> <Contact> <address> -1 Infinite Loop </address> <phone> <LandLine>(000) 555-5555</LandLine>

我正试图用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>
我是XML/C#的新手,但上面的方法只会发出糟糕的代码!我希望确保,如果结构发生变化(即,存在诸如“mobile”之类的附加电话号码类型),则代码是健壮的(因此会出现附加的while循环)

注意:上面的C#代码并不精确,并且缺少一些检查等,但它展示了我目前糟糕透顶的方法


如果这两个元素存在,那么从中提取内容的最佳/最干净的方法是什么

下面的文章可能有用


以下文章可能有用

使用:

var doc=XDocument.Parse(@)
上下快速移动
-1无限循环
(000) 555-5555
(000) 555-5556 
foo@bar.com 
");
var phone=doc.Root.Element(“联系人”).Element(“电话”);
Console.WriteLine((字符串)phone.Element(“固定线路”);
Console.WriteLine((字符串)phone.Element(“Fax”);
输出:

(000) 555-5555 (000) 555-5556 (000) 555-5555 (000) 555-5556 使用:

var doc=XDocument.Parse(@)
上下快速移动
-1无限循环
(000) 555-5555
(000) 555-5556 
foo@bar.com 
");
var phone=doc.Root.Element(“联系人”).Element(“电话”);
Console.WriteLine((字符串)phone.Element(“固定线路”);
Console.WriteLine((字符串)phone.Element(“Fax”);
输出:

(000) 555-5555 (000) 555-5556 (000) 555-5555 (000) 555-5556
最好的方法是使用XPath。请参阅本文,以供参考:


这篇文章介绍了如何做到这一点:

最好的方法是使用XPath。请参阅本文,以供参考:


这篇文章介绍了如何做到这一点:

对于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;
}

对于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;
}

我不认为你离得太远。有更方便的方法(许多不同的方法)。假设您希望采用与此处相同的基本方法(这是一种有效的方法,尽管非常详细),我会:

请注意,这将跟踪它是否在“电话”元素中,在该元素中,您所拥有的内容将在稍后的元素中重新检查固定线路,而您似乎正试图避免这样做


还要注意的是,我们清理了XmlReader,并在获得所需的所有信息后立即返回。

我不认为您离得太远。有更方便的方法(许多不同的方法)。假设您希望采用与此处相同的基本方法(这是一种有效的方法,尽管非常详细),我会:

请注意,这将跟踪它是否在“电话”元素中,在该元素中,您所拥有的内容将在稍后的元素中重新检查固定线路,而您似乎正试图避免这样做


还请注意,我们会清理XmlReader,并在获得所需的所有信息后立即返回。

注意,如果缺少联系人,您将在
var phone=…
行中遇到异常。我喜欢做一些事情,比如
var contactNode=doc.Root.Element(“Contact”)??新XElement(“联系人”)所以我总是返回一个节点,然后当我执行
var phone=contact.Element(“phone”)时??新XElement(“电话”)我不会得到空对象错误。最后,我得到了变量的空白值。或者在解析之前使用xsd验证文档,以确保您想要的节点存在;通常不是对文档中的节点进行只读随机访问所需的,尤其是在处理大型文档时。请注意,如果缺少联系人,则会在
var phone=…
行中出现异常。我喜欢做一些事情,比如
var contactNode=doc.Root.Element(“Contact”)??新XElement(“联系人”)所以我总是返回一个节点,然后当我执行
var phone=contact.Element(“phone”)时??新XElement(“电话”)我不会得到空对象错误。最后,我得到了变量的空白值。或者在解析之前使用xsd验证文档,以确保您想要的节点存在;通常不是对文档中的节点进行只读随机访问所需的,尤其是在处理大型文档时。这可以工作,但对于只读访问来说并不理想。该示例使用
XmlDocument
,它在内存中构建了一个通常不需要的完整DOM树。该示例使用
XmlDocument
,它在内存中构建了一个通常不需要的完整DOM树。
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;
  }
}