Cómo especificar el espacio de nombres cuando se consulta el DOM con XPath


Resumen


Con el lanzamiento de Microsoft XML Parser (MSXML) 3.0, XPath proporciona una forma cómoda para consultar documentos XML y devolver un nodo o en conjunto. Cuando se utiliza la consulta XPath con los métodos selectSingleNode y selectNodes del objeto IXMLDOMNode , debe utilizar nombres completos. Por ejemplo, para seleccionar el nodo de libro con los siguientes datos XML
<?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>


Si utilizamos un como el alias de x-schema:bookschema.xml identificador de recursos uniforme (URI), la consulta de XPath correspondiente es el siguiente:
pXMLDoc->setProperty("SelectionNamespaces","xmlns:a='x-schema:bookschema.xml'");pXMLDoc->documentElement->selectNodes("/a:Books/a:Book");

En este caso, utilizando el nombre completo es sencillo. Cuando se utiliza el espacio de nombres predeterminado, sin embargo, utilizando el nombre completo puede ser más difícil, como en el ejemplo siguiente:
<?xml version ="1.0"?><Books xmlns="x-schema:bookschema.xml" >
<Book>
<title>Presenting XML</title>
<author>Richard Light</author>
</Book>
</Books>


Tenga en cuenta que en las etiquetas de nodo no se utiliza ningún prefijo. Debe utilizar el nombre completo dentro de la consulta XPath, de lo contrario la consulta (por ejemplo, /Books/Book) no devuelve ningún resultado porque no hay ningún nodo coincidente.

Más información


En el siguiente ejemplo de Visual C++ se proporciona para ilustrar la técnica.

Para especificar el espacio de nombres cuando consulta el DOM con XPath, siga estos pasos:
  1. Cree un proyecto de consola Win32 y agregue un nuevo archivo .cpp al proyecto. Pegue el código siguiente en el archivo .cpp y nombre del archivo 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. Guarde el siguiente código XML como Books.xml en la misma carpeta de proyecto que 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. Guarde el siguiente código XML como Bookschema.xml en la misma carpeta de proyecto que Test.cpp.
    <?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. Compile y ejecute la aplicación. Un cuadro de mensaje muestra el número de nodos que son devueltos por la consulta XPath.
Tenga en cuenta lo siguiente:
  • El mismo código de ejemplo se puede utilizar con un URI explícito como un espacio de nombres.
  • En las siguientes líneas
    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");

    el método setProperty no está disponible con la interfaz IXMLDOMDocument .
Un nombre completo (QName) se compone de un prefijo y una parte local. El prefijo proporciona el prefijo de espacio de nombres del nombre completo y debe estar asociado con un identificador URI de espacio de nombres.

Referencias


Para obtener información adicional, haga clic en el número de artículo siguiente para verlo en Microsoft Knowledge Base:

288147 PRB: utilizar XPath para la consulta en un espacio de nombres predeterminado definido por el usuario