2013-05-10 86 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