如何使用MSXML查询默认命名空间

时间:2013-05-10 21:06:35

标签: xml-namespaces msxml msxml6

我有一些XML:

<?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

实际上,我的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。您使用名称空间管理器,为默认名称空间命名,然后使用该名称进行查询,然后您可以查询非默认名称空间,因为它不再是默认名称

  • 可以从我收到的XML字符串中删除令人反感的xmlns文字,但我宁愿“以正确的方式做”

如何使用MSXML查询“default”“unnamed”命名空间?


注意:实际上,我正在使用SQL Server的XML ShowPlan 输出:

<?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

我如何获取默认命名空间?

实际上,我并不关心命名空间 care 。我的查询很有意义,我想让它发挥作用。所以,问题的另一种方法可能是:

  

我如何查询默认命名空间是否,或者无论什么,该命名空间名称是(或不是)?

注意:msxml是 native 代码,并使用本机Win32编译器(即没有.NET框架或CLR)

1 个答案:

答案 0 :(得分:14)

将名称空间添加到SelectionNamespaces

时,明确地为名称空间命名
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);
    }