在C#中使用Ling解析xml

时间:2018-08-31 10:19:17

标签: c# xml linq

嗨,我有一个Xml文档,使用来读取文件

var doc = XDocument.Load(reader);

xml看起来像这样

<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE document SYSTEM 'xmlschemas/some.dtd'>
<document xmlns='http://www.abcd.com/dxl' version='9.0' someversion='1.0' 
          replicaid='0xxxxDB' form='Test'>
   <item name='From'>
      <text>John Doe</text>
   </item>
   <item name='SentTo'>
      <text>Another John Doe</text>
   </item>
   <item name='ModTime'>
      <datetime dst='true'>20180129T114649,22-02</datetime>
   </item>
   <item name='Body' sign='true' seal='true'>
       <attachmentref name='some.pdf' displayname='some.pdf'>
           <picture height='34px' width='342px'>
                <notesbitmap>
                    lQAmAAAAAAAAAAAAAAABAAAAAAAAAFYBI
                </notesbitmap>
           </picture>

在定位具有特定名称属性的“ item”标签时,如何使用Linq解析此类xml? 尝试过但没有成功。

 doc.Descendants("document")
 .Where(item =>
 {
    string cus = (string)item.Element("item");
    return cus != null && cus == "name";
 })
 .Descendants("SentTo")
 .Select(d => d.Value)
 .ToList();

我想使用名称属性为“发件人”和“ SentTo”的商品标签,还有其他一些我可能不想定位的标签。 预先感谢。

4 个答案:

答案 0 :(得分:4)

部分问题是您要查找没有名称空间的元素,但是文档确实指定了默认名称空间。幸运的是,LINQ to XML使名称空间的处理变得容易。

您还使用Descendants来查找属性的值(我相信),但这不是它的工作原理。

以下是起作用的示例-假设您的目标是从每个<text>元素中获得<item>内容,且其name属性为{{ 1}}:

SentTo

答案 1 :(得分:2)

您不想使用HtmlAgilityPack进行XML解析。但是,如果您知道为什么可能是一个问题,但仍然接受此决定,则可以执行以下操作:

var relevantItems = doc.DocumentNode
    .Descendants("item")
    .Select(x => new
    {
        Item = x,
        ItemName = x.Attributes.Contains("name") ? x.Attributes["name"].Value : null
    })
    .Where(x => x.ItemName == "From" || x.ItemName == "SentTo")
    .Select(x => x.Item)
    .ToList();

答案 2 :(得分:1)

您的xml包含namespace。因此,您还必须在代码中阅读该名称空间

XDocument doc = XDocument.Load(@"XMLFile1.xml");
XNamespace ns = doc.Root.GetDefaultNamespace();

var text = doc.Descendants(ns + "item")
              .Single(c => c.Attribute("name").Value == "SentTo")
              .Elements(ns + "text")
              .Select(item => (string)item)
              .FirstOrDefault();

输出:

enter image description here

因此,如果您要采用多个name属性text节点,则

//This is sample string of array
string[] strArray = new string[2] { "From", "SentTo" };

var list = doc.Descendants(ns + "item")
              .Where(c => strArray == null || strArray.Any(x => x.Contains(c.Attribute("name").Value)))
              .Elements(ns + "text")
              .Select(item => (string)item)
              .ToList();

输出:

enter image description here

答案 3 :(得分:0)

我可能会使类Item具有我需要的属性和属性,然后将XML反序列化到其中,稍后,我将使用LINQ来过滤值。在这里看看:

How to Deserialize XML document

http://www.janholinka.net/Blog/Article/11

我希望这会有所帮助。