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:
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); }
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>
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>
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'interfacciaIXMLDOMDocument
.
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