2012-05-23 10 views
7

che voglio fare una query XPath su questo file (estratto mostrati):Java XPath: Query con xmlns namespace di default

<?xml version="1.0" encoding="UTF-8"?> 
<!-- MetaDataAPI generated on: Friday, May 25, 2007 3:26:31 PM CEST --> 
<ModelClass xmlns="http://xml.sap.com/2002/10/metamodel/webdynpro" xmlns:IDX="urn:sap.com:WebDynpro.ModelClass:2.0"> 
    <ModelClass.Parent> 
     <Core.Reference package="com.test.mypackage" name="ModelName" type="Model"/> 

Si tratta di un frammento di codice che sto utilizzando:

DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance(); 
DocumentBuilder builder = domFactory.newDocumentBuilder(); 
Document document = builder.parse(new File(testFile)); 
XPathFactory factory = XPathFactory.newInstance(); 
XPath xpath = factory.newXPath(); 
xpath.setNamespaceContext(new NamespaceContext() { 
    public String getNamespaceURI(String prefix) { 
... 

String result = xpath.evaluate(xpathQueryString, document); 
System.out.println(result); 

Il problema che sto affrontando è che quando lo spazio dei nomi predefinito viene fatto riferimento in una query XPath, il metodo getNamespaceURI non viene chiamato per risolverlo. Questa query ad esempio, non consente di estrarre nulla:

//xmlns:ModelClass.Parent/xmlns:Core.Reference[@type=\"Model\"]/@package

Ora ho provato a "ingannare" il parser sostituendo xmlns con un prefisso falso d e poi a scrivere il metodo getNamespaceURI di conseguenza (si fa per tornare http://xml.sap.com/2002/10/metamodel/webdynpro quando viene rilevato d). In questo caso, viene chiamato getNamespaceURI ma il risultato della valutazione dell'espressione XPath è sempre una stringa vuota.

Se spoglio gli spazi dei nomi dal file e dall'espressione di query XPath, posso ottenere la stringa desiderata (com.test.mypackage).

C'è un modo per far funzionare le cose correttamente con lo spazio dei nomi predefinito?

risposta

8

Nella tua Namespace contesto, legare un prefisso di vostra scelta (ad esempio df) per lo spazio dei nomi URI nel documento

xpath.setNamespaceContext(new NamespaceContext() { 
    public String getNamespaceURI(String prefix) { 
     switch (prefix) { 
     case "df": return "http://xml.sap.com/2002/10/metamodel/webdynpro"; 
     ... 
     } 
    }); 

e quindi utilizzare tale prefisso nelle espressioni di percorso per qualificare i nomi degli elementi per esempio /df:ModelClass/df:ModelClass.Parent/df:Core.Reference[@type = 'Model']/@package.

+0

Ciao Martin, l'ho provato ma non funziona ... –

+4

Assicurati di creare anche un DocumentBuilder con lo spazio dei nomi http://docs.oracle.com/javase/6/docs/api/javax/ xml/parsers/DocumentBuilderFactory.html # setNamespaceAware% 28boolean% 29 prima di lavorare con namespace. –

+0

Questo ha fatto il trucco. Pensavo che DocumentBuilder fosse per impostazione predefinita al corrente degli spazi dei nomi. Grazie ancora. –

10

La specifica XPath 1.0 richiede che "nessun prefisso non significhi spazio dei nomi". Quindi JAXP, che è stato progettato per XPath 1.0, ha perfettamente ragione di non vincolare il "prefisso nullo" ad uno spazio dei nomi non nullo.

XPath 2.0 consente di dichiarare uno spazio dei nomi predefinito per nomi non qualificati nell'espressione XPath, ma per trarne vantaggio è necessaria un'API (come Saxon s9api) che sfrutta questa funzione.

+0

Grazie Michael per le informazioni aggiuntive. –