【问题标题】:Easiest way to filter elements out of an XML document in .NET在 .NET 中从 XML 文档中过滤元素的最简单方法
【发布时间】:2012-02-14 23:20:24
【问题描述】:

假设我有以下文档

<sets version="2.0">
  <setting>
    <id>set1</id>
    <value>80</value>
    <label>EVersion</label>
    <type>Val</type>
    <format>R</format>
    <bits>
      <addr>0</addr>
      <startBit>0</startBit>
      <bitWidth>8</bitWidth>
    </bitspec>
  </setting>
  <setting>
    <id>set3</id>
    <value>50</value>
    <label>GVersion</label>
    <type>Bin</type>
    <format>R</format>
    <bits>
      <addr>0</addr>
      <startBit>0</startBit>
      <bitWidth>8</bitWidth>
    </bitspec>
  </setting>
  </sets>

我只想要 ID 和 value 元素 -

<sets version="2.0">
  <setting>
    <id>set1</id>
    <value>80</value>
  </setting>
  <setting>
    <id>set3</id>
    <value>50</value>
  </setting>
  </sets>

如何使用 XDocument 和 LINQ 只选择这些?

【问题讨论】:

    标签: c# .net xml linq-to-xml


    【解决方案1】:

    使用linq-to-xml,代码如下:

    var xml_str = @"<sets version=""2.0"">
      <setting>
        <id>set1</id>
        <value>80</value>
        <label>EVersion</label>
        <type>Val</type>
        <format>R</format>
        <bits>
          <addr>0</addr>
          <startBit>0</startBit>
          <bitWidth>8</bitWidth>
        </bits>
      </setting>
      <setting>
        <id>set3</id>
        <value>50</value>
        <label>GVersion</label>
        <type>Bin</type>
        <format>R</format>
        <bits>
          <addr>0</addr>
          <startBit>0</startBit>
          <bitWidth>8</bitWidth>
        </bits>
      </setting>
      </sets>";
    
    var doc = XDocument.Parse(xml_str);
    
    var settings = new XElement("sets",
        from setting in doc.Element("sets").Elements("setting")
        select new XElement("setting", setting.Element("id"), setting.Element("value")));
    
    Console.WriteLine(settings);
    

    打印:

    <sets>
      <setting>
        <id>set1</id>
        <value>80</value>
      </setting>
      <setting>
        <id>set3</id>
        <value>50</value>
      </setting>
    </sets>
    

    如果您不需要转换后的 XML,而只需要 id -&gt; value 映射的字典(将 value 存储为 int),您可以这样做:

    var doc = XDocument.Parse(xml_str);
    var settings_dict = doc.Element("sets").Elements("setting").ToDictionary(s => s.Element("id").Value, s => Convert.ToInt32(s.Element("value").Value));
    

    【讨论】:

      【解决方案2】:
      var xdoc = XDocument.Load(@"c:\myxml.xml");
      
      var settings = 
          xdoc.Element("sets").Elements("setting")
          .Select(s => new 
             { 
               Id = s.Element("id").Value, 
               Value = s.Element("value").Value 
             });
      

      这将产生一个匿名类型的IEnumerable,具有属性IdValue(两个字符串)。

      您可以创建自己的 Setting 类型,并在投影中使用它,如果需要,还可以将“值”字符串值转换为整数。

      【讨论】:

        【解决方案3】:

        我的第一个答案与其他答案非常相似,并且不太清楚,因此我将其删除。但是,我认为编写一些 linq 以在所需元素处于任意深度时生成过滤后的 XML 将是一个很好的练习。这是我想出的:

        Func<XElement, XElement> f = null; 
        f = e => e.Name == "id" || e.Name == "value" ? e : //on a match, return the node
            new[] { new XElement(e.Name, e.Elements().Select(f)) } //else recurse
            .FirstOrDefault(y => y.Elements().Any()); //keeping subtrees with matches
        
        XElement resultXmlElement = f(XDocument.Parse(yourXmlString).Root);
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-10-28
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多