2015-06-23 110 views
0

我有一个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?

回答

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> 
+0

这不回答这个问题 - 在属性'测试:货币'仍然存在。 '.Descendants'返回一个枚举的XElement。 –

+1

@MatJones对不起,我确实错过了这个问题的部分,修正了它。遍历元素,然后通过属性看起来不太难看,恕我直言。你怎么看? – har07

+1

当然,你已经在'.Descendants()'的返回值上使用了'.Attributes()'!这很好,我喜欢可读性,而且当我看到你写的东西的时候,我实际上会打我的额头。看到它,我现在无法相信我没有意识到我可以自己做到这一点!非常感谢。 –

1

试试这个。我不得不把从根元素的命名空间,然后运行两个独立的Linqs:

  1. 移除与命名空间的元素
  2. 删除属性与命名空间

代码:

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语句的这条线,你得到namespaceValue后

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

结果:

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

它确实有效,但我更喜欢@ har07的问题中的LINQ,但有一个用于提出变体的+1。非常感谢。 –

相关问题