2013-05-10 96 views
11

我有一些XML:如何查詢默認的命名空間與MSXML

<?xml version="1.0" ?> 
<Project ToolsVersion="4.0"> 
    <PropertyGroup Condition="'$(key)'=='1111'"> 
      <Key>Value</Key> 
    </PropertyGroup> 
</Project> 

注意:這不是實際的XML我使用,它只是漂亮,更短,並演示了此問題。

使用MSXML我可以爲節點查詢:

IXMLDOMNode node = doc.selectSingleNode("//PropertyGroup/@Condition"); 

,它工作正常:

條件= 「 '$(密鑰)' == '1111'」

但這不是真的我有我的

實際上,我有XML包含一個名稱空間聲明:

的xmlns = 「http://schemas.microsoft.com/developer/msbuild/2003」

使得實際 XML文檔:

<?xml version="1.0" ?> 
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> 
    <PropertyGroup Condition="'$(key)'=='1111'"> 
      <Key>Value</Key> 
    </PropertyGroup> 
</Project> 

現在我的查詢:

IDOMNode node = doc.selectSingleNode("//PropertyGroup/@Condition"); 

返回沒有匹配的節點。

如何使用MSXML查詢默認名稱空間?

注意

  • 我已經知道how to query the non-default namespace in xml;您使用:

    doc.setProperty("SelectionNamespaces", 
         "xmlns="http://schemas.microsoft.com/developer/msbuild/2003"); 
    
  • 我已經知道how to query the default namespace in .NET。您可以使用命名空間管理,給默認的命名空間的名稱,然後查詢中使用該名稱,然後你就可以查詢非默認的命名空間,因爲它不再默認

  • 可以剛剛刪除的進攻xmlns文本XML字符串我接受,但我寧願「做正確的方式」

我如何查詢「默認」,或「無名」命名空間使用MSXML?


注意:在現實中,XML我使用的是SQL Server的XML 顯示計劃輸出:

<?xml version="1.0" encoding="UTF-16" standalone="yes"?> 
    <ShowPlanXML Version="1.1" Build="10.50.1600.1" 
        xmlns="http://schemas.microsoft.com/sqlserver/2004/07/showplan"> 
     <BatchSequence> 
      <Batch> 
      ... 
      </Batch> 
     </BatchSequence> 
    </ShowPlanXML> 

同樣,你可以看到有問題的命名空間聲明。刪除它的作品,但這是乏味的。

你還試過了什麼?

我也嘗試設置SelectionNamespace

doc.setProperty('SelectionNamespaces', 
     'xmlns="http://schemas.microsoft.com/developer/msbuild/2003"'); 

Microsoft hints at in a KB article

我該如何得到的默認命名空間?

事實上,我不知道關於命名空間的護理。我的查詢是有道理的,我希望它工作。所以,這個問題的另一種方法可能是:

我如何可以查詢默認的命名空間是否與否,也不管該命名空間的名字是什麼,(或者不是)?

注意:MSXML是本地代碼,並使用它從一個本機Win32編譯器(即沒有.NET Framework或CLR)

+0

我做了一個更新。它從電影院開車回家時撞到了我。 – granadaCoder 2013-05-11 02:54:14

+0

@granadaCoder你在看電影時正在回答StackOverflow!? – 2013-05-11 15:12:27

+0

在回家的路上,我給了我幾個CPU「循環」的東西.....我的收音機剛剛死在我身上。 – granadaCoder 2013-05-11 15:29:42

回答

14

明確給出的命名空間的名字,當你把它添加到​​:

doc.setProperty("SelectionNamespaces", 
     "xmlns:peanut='http://schemas.microsoft.com/developer/msbuild/2003'"); 

,然後查詢使用該命名空間:

IDOMNode node = doc.selectSingleNode("//peanut:PropertyGroup/@Condition"); 

您可以爲該名稱空間提供所需的任何縮寫名稱(在這種情況下爲peanut)。然後使用縮寫作爲前綴(在這種情況下爲peanut:PropertyGroup)。

早些時候建議

我會嘗試移動到Xml.Linq

下面是一個示例(帶有名稱空間)。

 try 
    { 

     XDocument xDoc1 = XDocument.Parse("<?xml version=\"1.0\" ?><Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\"><PropertyGroup Condition=\"'$(key)'=='1111'\"><Key>Value</Key></PropertyGroup></Project>"); 
     XNamespace ns1 = XNamespace.Get("http://schemas.microsoft.com/developer/msbuild/2003"); 

     var list1 = from list in xDoc1.Descendants(ns1 + "Project") 
        from item in list.Elements(ns1 + "PropertyGroup") 
        /* where item.Element(ns + "HintPath") != null */ 
        where item.Attribute("Condition") != null 
        select new 
        { 
         MyCondition = item.Attribute("Condition") == null ? "Not Here!" : item.Attribute("Condition").Value, 
         MyFake = item.Attribute("DoesNotExistTest") == null ? "Not Here Sucker!" : item.Attribute("DoesNotExistTest").Value 
        }; 


     foreach (var v in list1) 
     { 
      Console.WriteLine(v.ToString()); 
     } 


     XDocument xDoc2 = XDocument.Parse("<?xml version=\"1.0\" encoding=\"UTF-16\" standalone=\"yes\"?> <ShowPlanXML Version=\"1.1\" Build=\"10.50.1600.1\"     xmlns=\"http://schemas.microsoft.com/sqlserver/2004/07/showplan\">  <BatchSequence>   <Batch>Something I Threw In Here</Batch>  </BatchSequence> </ShowPlanXML> "); 
     XNamespace ns2 = XNamespace.Get("http://schemas.microsoft.com/sqlserver/2004/07/showplan"); 

     var list2 = from list in xDoc2.Descendants(ns2 + "ShowPlanXML") 
        from item in list.Elements(ns2 + "BatchSequence") 
        /*        where item.Attribute("Condition") != null */ 
        where item.Element(ns2 + "Batch") != null 
        select new 
        { 
         BatchValue = (item.Element(ns2 + "Batch") == null) ? string.Empty : item.Element(ns2 + "Batch").Value 
        }; 


     foreach (var v in list2) 
     { 
      Console.WriteLine(v.ToString()); 
     } 



    } 
    catch (Exception ex) 
    { 
     Console.WriteLine(ex.Message); 
    } 
+0

對不起,'IXMLDOMNode',不是'IDOMNode'。它來自***本地*** msxml COM對象庫。這是從本地不是(即不是.NET) – 2013-05-10 21:25:38

+0

好吧。檢查我的更新提示。我猜測,但數字比留下剛剛的.Net響應要好。 – granadaCoder 2013-05-10 21:40:48

+0

我忘了給你答案;那工作。在使用它之前,你必須命名默認名稱空間是非常可怕的。但至少這是一個可行的解決方案! – 2013-05-13 13:30:16