Specificare spazio dei nomi quando si esegue una query sul DOM con XPath

Questo articolo descrive che è necessario usare nomi qualificati quando si usa la query XPath con i metodi selectSingleNode e selectNodes dell'oggetto IXMLDOMNode .

Versione originale del prodotto: Microsoft XML Parser
Numero KB originale: 294797

Riepilogo

Con la versione Parser XML (MSXML) 3.0, XPath offre un modo pratico per eseguire query sui documenti XML e restituire un nodo o un set di nodi. Quando si usa XPath la query con i selectSingleNode metodi e selectNodes dell'oggetto IXMLDOMNode , è necessario usare nomi qualificati. Ad esempio, per selezionare il nodo Book con i dati XML seguenti:

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

se si usa un oggetto come alias dell'URI x-schema:bookschema.xml (Uniform Resource Identifier), la query XPath corrispondente è la seguente:

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

In questo caso, l'uso del nome completo è semplice. Quando si usa lo spazio dei nomi predefinito, tuttavia, l'uso del nome completo può essere più difficile, come nell'esempio seguente:

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

Nota

Nei tag del nodo non viene usato alcun prefisso. Il nome completo deve ancora essere usato all'interno della query XPath, altrimenti la query (ad esempio, /Books/Book) non restituisce alcun risultato perché non sono presenti nodi corrispondenti.

Ulteriori informazioni

L'esempio di Visual C++ seguente viene fornito per illustrare la tecnica.

Per specificare lo spazio dei nomi quando si esegue una query sul DOM con XPath, seguire questa procedura:

  1. Creare un progetto console Win32 e aggiungere un nuovo file di .cpp al progetto. Incollare il codice seguente nel file .cpp e denominare il file 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. Salvare il codice XML seguente come Books.xml nella stessa cartella del progetto di 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. Salvare il codice XML seguente come Bookschema.xml nella stessa cartella del progetto di 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. Compilare ed eseguire l'applicazione. Una finestra di messaggio mostra il numero di nodi restituiti dalla XPath query. Vedere quanto segue:

    • Lo stesso codice di esempio può essere usato con un URI esplicito come spazio dei nomi.

    • Nelle righe seguenti

      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");
      

      il setProperty metodo non è disponibile con l'interfaccia IXMLDOMDocument .

Un nome completo (QName) è composto da un prefisso e da una parte locale. Il prefisso fornisce il prefisso dello spazio dei nomi del nome completo e deve essere associato a un URI dello spazio dei nomi.

Riferimenti

Come usare XPath per eseguire query su uno spazio dei nomi predefinito definito dall'utente