Working with XDocument

本文关键字:XDocument with Working | 更新日期: 2023-09-27 18:27:24

我有以下XDocument:

<?xml version="1.0" encoding="utf-8"?>
   <D:multistatus xmlns:D="DAV:" xmlns:Office="urn:schemas-microsoft-com:office:office"    xmlns:Repl="http://schemas.microsoft.com/repl/" xmlns:Z="urn:schemas-microsoft-com:">
   <D:response>
       <D:href>http://aaa</D:href>
       <D:propstat>
           <D:prop>
               <D:displayname>a</D:displayname>
               <D:isFolder>t</D:isFolder>
           </D:prop>
           <D:status>HTTP/1.1 200 OK</D:status>
      </D:propstat>
  </D:response>
  <D:response>
        .
        .
  </D:response>  

如何获得所有回复?("D:response"标签下的所有内容,以及"D:propstat"answers"D:prop"标签下所有内容-我想得到D:href,D:displayname,D:isFolder)

我在做这个:

XNamespace d = "DAV:";
foreach (var file in doc.Descendants(d + "response"))
{
    if ((string)file.Element(d + "href") != (string)Configuration.Configs["baseUrl"])
    {
        string ref = (string)file.Element(d + "href");
        foreach (var propstat in file.Descendants(d + "propstat"))
            foreach (var prop in propstat.Descendants(d + "prop"))
            {
                string name = (string)prop.Element(d + "displayname");
                if (prop.Element(d + "isFolder") != null && (string)prop.Element(d + "isFolder") == "t")
                    string type = "folder";
                else
                    string type = "file";
            }
    }
} 

有更好的方法吗?

Working with XDocument

您可以这样做。它有点笨拙,但可以

var result = doc.Descendants(d + "response")
                .Select(x => new { href = x.Element(d + "href"), nodes = x.Descendants(d + "prop") })
                .Select(y => new
   {
      href = (string)y.href.Value,
      displayname = (string)y.nodes.Select(z => z.Element(d + "displayname")).First().Value,
      isFolder = (string)y.nodes.Select(z => z.Element(d + "isFolder")).First().Value
   }).ToList();

您可以简单地在查询中引入新的范围变量:

XNamespace d = "DAV:";
var responses = from r in xdoc.Descendants(d + "response")
                let propstat = r.Element(d + "propstat")
                let prop = propstat.Element(d + "prop")
                let isFolder = (string)prop.Element(d + "isFolder")
                select new
                {
                    Href = (string)r.Element(d + "href"),
                    Status = (string)propstat.Element(d + "status"),
                    Name = (string)prop.Element(d + "displayname"),
                    Type = (isFolder == null || isFolder == "t") ? 
                           "folder" : "file"
                };

注意:此答案假设您的响应将包含一个propstat元素,其中包含一个prop元素。

你可以试试这个:

using System;
using System.IO;
using System.Linq;
using System.Xml.Linq;
class Program
{
    static void Main(string[] args)
    {
        var xml = File.ReadAllText("input.xml");
        var ns = "DAV:";
        var doc = XDocument.Parse(xml);
        doc.Descendants(XName.Get("displayname", ns))
            .ToList().ForEach(dn =>
        {
            var isFolder = ((XElement)dn.NextNode).Value;
            var href = ((XElement)dn.Parent.Parent.PreviousNode).Value;
            Console.WriteLine("{0} {1} {2}", href, dn.Value, isFolder);
        });
    }
}

或者像这样:

doc.Descendants(XName.Get("response", ns))
    .ToList().ForEach(r =>
{
    var href = r.Descendants(XName.Get("href", ns))
        .First().Value;
    r.Descendants(XName.Get("displayname", ns))
        .ToList().ForEach(dn => {
        var isFolder = ((XElement)dn.NextNode).Value;
        Console.WriteLine("{0} {1} {2}", href, dn.Value, isFolder);
    });
});

在您的场景中,我强烈建议使用XPath

''D:response获取文档中的所有D:response元素

''D:response'D:href所有href元素

''D:response'D:propstat'D:prop'D:displayname所有displayName元素

''D:response'D:propstat'D:prop'D:isFolder所有isFolder元素

如果您需要一个相对路径,只需放下''。请在我提供的链接中阅读更多关于XPath的内容。这肯定值得你投资。