简体   繁体   English

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

[英]Remove all nodes in a specified namespace from XML

I have an XML document that contains some content in a namespace. 我有一个XML文档,其中包含命名空间中的某些内容。 Here is an example: 这是一个例子:

<?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>

I want to remove all of the content that is within the test namespace - not just remove the namespace prefix from the tags, but actually remove all nodes (elements and attributes) from the document that (in this example) are in the test namespace. 我想删除所有为中内容的test命名空间-不只是从标签中删除命名空间的前缀,但实际上除去所有节点从(在这个例子中)是在文档(元素和属性) test的命名空间。 My required output is: 我需要的输出是:

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

I'm currently not overly concerned if the namespace declaration is still present, for now I'd be happy with removing just the content within the specified namespace. 我现在不太担心名称空间声明是否仍然存在,现在我很乐意只删除指定名称空间中的内容。 Note that there may be multiple namespaces in the document to be modified, so I'd like to be able to specify which one I want to have the content removed. 请注意,文档中可能有多个名称空间需要修改,因此我希望能够指定要删除内容的名称空间。

I've tried doing it using .Descendants().Where(e => e.Name.Namespace == "test") but that is only for returning an IEnumerable<XElement> so it doesn't help me with finding the attributes, and if I use .DescendantNodes() I can't see a way of querying the namespace prefix as that doesn't seem to be a property on XNode. 我已经尝试过使用.Descendants().Where(e => e.Name.Namespace == "test")来做到这一点,但这仅用于返回IEnumerable<XElement>因此对我查找属性没有帮助。 ,如果使用.DescendantNodes() ,则无法看到查询名称空间前缀的方法,因为这似乎不是XNode上的属性。

I can iterate through each element and then through each attribute on the element checking each one's Name.Namespace but that seems inelegant and hard to read. 我可以遍历每个元素,然后遍历元素上的每个属性,以检查每个人的Name.Namespace但这似乎Name.Namespace优雅且难以阅读。

Is there a way of achieving this using LINQ to Xml? 有没有一种方法可以使用LINQ to Xml来实现?

Iterating through elements then through attributes seems not too hard to read : 遍历元素然后遍历属性似乎并不难理解:

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());

output : 输出:

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

Give this a try. 试试看。 I had to pull the namespace from the root element then run two separate Linqs: 我必须从根元素中提取名称空间,然后运行两个单独的Linq:

  1. Removes elements with the namespace 删除具有名称空间的元素
  2. Removes attributes with the namespace 用名称空间删除属性

Code: 码:

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());
}

Results: 结果:

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

If you want to remove the namespace from the root element add the this line in the if statement after you get the namespaceValue 如果要从根元素中删除名称空间,请在获取namespaceValue之后在if语句中添加此行

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

Results: 结果:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM