【问题标题】:Get the root element with filtered children获取带有过滤子元素的根元素
【发布时间】:2012-02-04 18:19:57
【问题描述】:

对于以下 Xml:

<A>
  <B id=1>
    <C id=2 />
  </B>
  <B id=3>
    <C id=4 />
  </B>
</A>

我想通过 C 的 Id 值为 4 来获得此结果:

<A>
  <B id=3>
    <C id=4 />
  </B>
</A>

那么,最好的解决方案是什么?

【问题讨论】:

  • 那么,你想获取元素B,其子C的id是4?
  • 结构总是一样的吗?标记名称? &lt;B id=4&gt; 呢?
  • @KirillPolishchuk : 我想要 A 和过滤的孩子
  • @Henk Holterman:是的,我需要定义 C_id 值并获得带有过滤子项的 A。
  • 使用 SQL XQuery.modify('delete(//*[not(descendant-or-self::B[@id=3]) 和 descendant::B] )') 更容易! !!

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


【解决方案1】:

假设您有一个 XDocument 代表您的 XML 结构

var doc = XDocument.Parse(@"<A>
  <B id='1'>
    <C id='2' />
  </B>
  <B id='3'>
    <C id='4' />
  </B>
</A>");

还有一个XElement 代表该文档中带有id='4' 的元素

XElement x = doc.Descendants().Single(e => (int?)e.Attribute("id") == 4);

您可以构造一个由该元素及其父元素组成的新XDocument,如下所示:

XElement y = x;

while (x.Parent != null)
{
    x = x.Parent;
    y = new XElement(x.Name, x.Attributes(), y);
}

XDocument result = new XDocument(y);

结果:

<A>
  <B id="3">
    <C id="4" />
  </B>
</A>

【讨论】:

    【解决方案2】:

    用途:

    var doc = XDocument.Parse(@"<A>
    <B id='1'>
    <C id='2' />
    </B>
    <B id='3'>
    <C id='4' />
    </B>
    </A>");
    
    var elementsToRemove = doc.Root.Elements("B")
        .Where(b => (int)b.Element("C").Attribute("id") != 4);
    
    elementsToRemove.Remove();
    
    Console.WriteLine(doc);
    

    输出:

    <A>
      <B id="3">
        <C id="4" />
      </B>
    </A>
    

    【讨论】:

      【解决方案3】:

      如果我明白,这就是你想要的:

      //*[descendant::C[@id=4]]
      

      即所有以 &lt;c id="4"/&gt; 为子元素的元素。

      顺便说一句,您的 XML 应该在数字周围加上引号才能形成良好的格式。

      【讨论】:

      • 此解决方案不会修剪不需要的元素!
      • 它应该 - 你能在例如这个 xpath 测试器:chris.photobooks.com/xml/default.htm。它将过滤到您作为示例提供的内容(即 A 下带有 B[@id=3],然后是 C[@id=4] 在 B 下)。这是你想要的吗?
      • 我需要元素 A 并从其子元素中删除不需要的 B。另外两个人做我想做的事。但理想的情况就是使用 XPath!
      • 你可以在一些在线 xpath 测试器中尝试它以确认它返回你想要的吗?尝试任何 - 例如这是您可以尝试的另一个 - mizar.dk/XPath/Default.aspx。当我输入您的 XML 和我的 xpath 选择器时,&lt;c id="4"/&gt; 的 A 和 B 被选中,仅此而已。如果你使用descendant-or-self,你会得到A、B和C。
      • 啊,我明白你在说什么。我不认为这是可能的。 XPath 是一种选择语言——它允许您精确选择节点,但不能转换它们。例如。你不能说“给我一个节点,只有它是第 5 个孩子”。您可以选择第 5 个孩子本身。要进行转换,您需要使用XSLT,但鉴于您使用的是 C#,其他答案可能比将 XSLT 引入图片更合适。
      猜你喜欢
      • 1970-01-01
      • 2015-05-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-07-22
      • 2014-05-06
      • 1970-01-01
      相关资源
      最近更新 更多