2012-05-23 8 views
7

que quiero hacer una consulta XPath en este archivo (extracto presentados):Java XPath: Las consultas con xmlns espacio de nombres predeterminado

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

Este es un fragmento de código que estoy usando:

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

El problema al que me enfrento es que cuando se hace referencia al espacio de nombre predeterminado en una consulta XPath, no se llama al método getNamespaceURI para resolverlo. Esta consulta, por ejemplo, no extrae nada:

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

Ahora he intentado "engañar" al analizador mediante la sustitución de xmlns con un prefijo falso d y luego escribir el método getNamespaceURI en consecuencia (por lo que volver http://xml.sap.com/2002/10/metamodel/webdynpro cuando se encuentra d). En este caso, se llama al getNamespaceURI pero el resultado de la evaluación de la expresión XPath siempre es una cadena vacía.

Si elimino los espacios de nombres del archivo y de la expresión de consulta XPath, puedo obtener la cadena que quería (com.test.mypackage).

¿Hay alguna manera de hacer que las cosas funcionen correctamente con el espacio de nombres predeterminado?

Respuesta

8

En el contexto Namespace, unir un prefijo de su elección (por ejemplo df) a la URI de espacio en el documento

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

y luego usar ese prefijo en sus expresiones de ruta para calificar los nombres de elementos, por ejemplo, /df:ModelClass/df:ModelClass.Parent/df:Core.Reference[@type = 'Model']/@package.

+0

Hola Martin, lo he intentado pero no funciona ... –

+4

Asegúrate también de crear un espacio de nombres compatible DocumentBuilder http://docs.oracle.com/javase/6/docs/api/javax/ xml/parsers/DocumentBuilderFactory.html # setNamespaceAware% 28boolean% 29 antes de trabajar con espacios de nombres. –

+0

Eso hizo el truco. Pensé que el DocumentBuilder estaba consciente de los espacios de nombres por defecto. Gracias de nuevo. –

10

La especificación XPath 1.0 requiere que "sin prefijo no signifique ningún espacio de nombre". Así que JAXP, que fue diseñado para XPath 1.0, es bastante correcto para evitar que vincule el "prefijo nulo" a un espacio de nombre no nulo.

XPath 2.0 le permite declarar un espacio de nombres predeterminado para nombres no calificados en su expresión XPath, pero para aprovecharlo necesitará una API (como s9api de Saxon) que aproveche esta característica.

+0

Gracias Michael por la información adicional. –

Cuestiones relacionadas