从 XML 中删除指定命名空间中的所有节点
Remove all nodes in a specified namespace from 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 实现此目的?
遍历元素然后遍历属性似乎不太难读:
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>
试一试。我不得不从根元素中提取命名空间,然后 运行 两个单独的 Linqs:
- 删除具有命名空间的元素
- 删除具有命名空间的属性
代码:
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>
如果您想从根元素中删除名称空间,请在获取名称空间值后在 if 语句中添加此行
xDocument.Root.Attributes().Where(a => a.IsNamespaceDeclaration).Remove();
结果:
<root>
<Item name="Item one">
<Price>124.00</Price>
</Item>
</root>
我有一个 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 实现此目的?
遍历元素然后遍历属性似乎不太难读:
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>
试一试。我不得不从根元素中提取命名空间,然后 运行 两个单独的 Linqs:
- 删除具有命名空间的元素
- 删除具有命名空间的属性
代码:
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>
如果您想从根元素中删除名称空间,请在获取名称空间值后在 if 语句中添加此行
xDocument.Root.Attributes().Where(a => a.IsNamespaceDeclaration).Remove();
结果:
<root>
<Item name="Item one">
<Price>124.00</Price>
</Item>
</root>