使用 XPath 查询 DOM 时指定命名空间

本文介绍在使用对象的 selectSingleNode 和 selectNodes 方法 IXMLDOMNode 进行 XPath 查询时,必须使用限定名称。

原始产品版本: Microsoft XML 分析器
原始 KB 数: 294797

总结

使用 XML 分析器 (MSXML) 3.0 版本, XPath 可以方便地查询 XML 文档并返回节点或节点集。 在使用XPath查询以及selectSingleNodeselectNodes方法与IXMLDOMNode对象配合时,必须使用限定名称。 例如,要选择带有以下 XML 数据的 Book 节点:

<?xml version ="1.0"?>
<a:Books xmlns:a="x-schema:bookschema.xml" >
    <a:Book>
        <title>Presenting XML</title>
        <author>Richard Light</author>
    </a:Book>
</a:Books>

如果我们用 a 作为 x-schema:bookschema.xml 统一资源标识符 (URI) 的别名,则相应的 XPath 查询如下:

pXMLDoc->setProperty("SelectionNamespaces","xmlns:a='x-schema:bookschema.xml'");
pXMLDoc->documentElement->selectNodes("/a:Books/a:Book");

在这种情况下,使用限定的名称非常简单。 但是,使用默认命名空间时,使用限定名称可能更加困难,如以下示例所示:

<?xml version ="1.0"?>
<Books xmlns="x-schema:bookschema.xml" >
    <Book>
        <title>Presenting XML</title>
        <author>Richard Light</author>
    </Book>
</Books>

注意

节点标记中不使用前缀。 限定名称仍必须在 XPath 查询中使用,否则查询(例如 ,/Books/Book)不会返回任何结果,因为没有匹配的节点。

详细信息

提供了以下 Visual C++ 示例来演示技术。

若要在使用 XPath 查询 DOM 时指定命名空间,请执行以下步骤:

  1. 创建 Win32 控制台项目,并向项目添加新.cpp文件。 将以下代码粘贴到.cpp文件中,并将文件命名为Test.cpp:

    #include <stdio.h>
    
    #import "msxml3.dll"
    using namespace MSXML2;
    
    void dump_com_error(_com_error &e);
    
    int main(int argc, char* argv[])
    {
        CoInitialize(NULL);
        try{
            IXMLDOMDocument2Ptr pXMLDoc;
            HRESULT hr = pXMLDoc.CreateInstance(__uuidof(DOMDocument));
    
            pXMLDoc->async = false; // default - true,
    
            pXMLDoc->validateOnParse = true;
    
            hr = pXMLDoc->load("books.xml");
    
            if(hr!=VARIANT_TRUE)
            {
                IXMLDOMParseErrorPtr pError;
    
                pError = pXMLDoc->parseError;
                _bstr_t parseError =_bstr_t("At line ")+ _bstr_t(pError->Getline()) + _bstr_t("\n")+
                _bstr_t(pError->Getreason());
                MessageBox(NULL,parseError, "Parse Error",MB_OK);
                return -1;
            }
    
            hr = pXMLDoc->setProperty("SelectionLanguage", "XPath");
            hr = pXMLDoc->setProperty("SelectionNamespaces", "xmlns:a='x-schema:bookschema.xml'");
    
            IXMLDOMNodeListPtr pNodeList;
            pNodeList = pXMLDoc->documentElement->selectNodes("/a:Books/a:Book");
            int count = pNodeList->Getlength();
            char pLength[64];
            sprintf(pLength, "Total number of nodes selected is %d", count);
            MessageBox(NULL,pLength,"Test", MB_OK);
    
        }
        catch(_com_error &e)
        {
            dump_com_error(e);
            return -1;
        }
        return 0;
    }
    
    void dump_com_error(_com_error &e)
    {
        printf("Error\n");
        printf("\a\tCode = %08lx\n", e.Error());
        printf("\a\tCode meaning = %s", e.ErrorMessage());
        _bstr_t bstrSource(e.Source());
        _bstr_t bstrDescription(e.Description());
        printf("\a\tSource = %s\n", (LPCSTR) bstrSource);
        printf("\a\tDescription = %s\n", (LPCSTR) bstrDescription);
    }
    
  2. 将以下 XML 另存为Books.xml与Test.cpp相同的项目文件夹中。

    <?xml version ="1.0"?>
    <Books xmlns="x-schema:bookschema.xml" >
    <Book>
    <title>Presenting XML</title>
    <author>Richard Light</author>
    <pages>334</pages>
    </Book>
    <Book>
    <title>Mastering XML</title>
    <author>John Smith</author>
    <pages>209</pages>
    </Book>
    </Books>
    
  3. 将以下 XML 另存为与Test.cpp相同的项目文件夹中Bookschema.xml。

    <?xml version="1.0"?>
    <Schema xmlns="urn:schemas-microsoft-com:xml-data">
    <ElementType name="title" />
    <ElementType name="author" />
    <ElementType name="pages" />
    <ElementType name="Book" model="closed">
    <element type="title" />
    <element type="author" />
    <element type="pages" />
    </ElementType>
    <ElementType name="Books" model="closed">
    <element type="Book" />
    </ElementType>
    </Schema>
    
  4. 编译并运行该应用程序。 消息框显示查询返回 XPath 的节点数。 参阅以下内容:

    • 同一示例代码可与显式 URI 一起使用作为命名空间。

    • 在以下行中

      IXMLDOMDocument2Ptr pXMLDoc;
      ...
      hr = pXMLDoc->setProperty("SelectionLanguage", "XPath");
      hr = pXMLDoc->setProperty("SelectionNamespaces", "xmlns:a='x-schema:bookschema.xml'");
      ...
      pNodeList = pXMLDoc->documentElement->selectNodes("/a:Books/a:Book");
      

      setProperty 方法在 IXMLDOMDocument 接口中不可用。

限定名称(QName)由前缀和本地部分组成。 该前缀提供限定名称的命名空间前缀,并且必须与命名空间 URI 相关联。

参考

如何使用 XPath 查询用户定义的默认命名空间