从XML中删除指定命名空间中的所有节点

时间:2015-06-23 13:33:01

标签: c# xml linq-to-xml

我有一个XML文档,其中包含命名空间中的一些内容。这是一个例子:

<?xml version="1.0" encoding="UTF-8"?>
<root xmlns:test="urn:my-test-urn">
    <Item name="Item one">
        <test:AlternativeName>Another name</test:AlternativeName>
        <Price test:Currency="GBP">124.00</Price>
    </Item>
</root>

我想删除test命名空间中的所有内容 - 不只是从标记中删除命名空间前缀,而是从文档中删除所有节点(元素和属性)(在此示例中) )位于test命名空间中。我要求的输出是:

<?xml version="1.0" encoding="UTF-8"?>
<root xmlns:test="urn:my-test-urn">
    <Item name="Item one">
        <Price>124.00</Price>
    </Item>
</root>

我目前并不过分关注命名空间声明是否仍然存在,现在我很乐意删除指定命名空间中的内容。请注意,要修改的文档中可能有多个名称空间,因此我希望能够指定要删除内容的名称。

我尝试使用.Descendants().Where(e => e.Name.Namespace == "test")进行此操作,但这仅用于返回IEnumerable<XElement>,因此它无法帮助我找到属性,如果我使用.DescendantNodes()我可以没有看到查询名称空间前缀的方法,因为它似乎不是XNode上的属性。

我可以遍历每个元素,然后遍历元素上的每个属性,检查每个元素的Name.Namespace,但这看起来不够优雅且难以阅读。

有没有办法使用LINQ to Xml来实现这个目标?

2 个答案:

答案 0 :(得分:1)

通过元素迭代然后通过属性似乎不难读:

var xml = @"<?xml version='1.0' encoding='UTF-8'?>
<root xmlns:test='urn:my-test-urn'>
    <Item name='Item one'>
        <test:AlternativeName>Another name</test:AlternativeName>
        <Price test:Currency='GBP'>124.00</Price>
    </Item>
</root>";
var doc = XDocument.Parse(xml);
XNamespace test = "urn:my-test-urn";

//get all elements in specific namespace and remove
doc.Descendants()
   .Where(o => o.Name.Namespace == test)
   .Remove();
//get all attributes in specific namespace and remove
doc.Descendants()
   .Attributes()
   .Where(o => o.Name.Namespace == test)
   .Remove();

//print result
Console.WriteLine(doc.ToString());

输出

<root xmlns:test="urn:my-test-urn">
  <Item name="Item one">
    <Price>124.00</Price>
  </Item>
</root>

答案 1 :(得分:1)

试一试。我不得不从根元素中拉出命名空间然后运行两个单独的Linqs:

  1. 使用命名空间
  2. 删除元素
  3. 使用命名空间
  4. 删除属性

    代码:

    string xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
        "<root xmlns:test=\"urn:my-test-urn\">" +
        "<Item name=\"Item one\">" +
        "<test:AlternativeName>Another name</test:AlternativeName>" +
        "<Price test:Currency=\"GBP\">124.00</Price>" +
        "</Item>" +
        "</root>";
    
    XDocument xDocument = XDocument.Parse(xml);
    if (xDocument.Root != null)
    {
        string namespaceValue = xDocument.Root.Attributes().Where(a => a.IsNamespaceDeclaration).FirstOrDefault().Value;
    
        // Removes elements with the namespace
        xDocument.Root.Descendants().Where(d => d.Name.Namespace == namespaceValue).Remove();
    
        // Removes attributes with the namespace
        xDocument.Root.Descendants().ToList().ForEach(d => d.Attributes().Where(a => a.Name.Namespace == namespaceValue).Remove());
    
        Console.WriteLine(xDocument.ToString());
    }
    

    结果:

    <root xmlns:test="urn:my-test-urn">
      <Item name="Item one">
        <Price>124.00</Price>
      </Item>
    </root>
    

    如果要从根元素中删除命名空间,请在获取namespaceValue后在if语句中添加此行

    xDocument.Root.Attributes().Where(a => a.IsNamespaceDeclaration).Remove();
    

    结果:

    <root>
      <Item name="Item one">
        <Price>124.00</Price>
      </Item>
    </root>