2015-06-23 111 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。非常感謝。 –

相關問題