2011-03-08 25 views
62

Tengo el siguiente código XML:Espacio de nombres Xml rompiendo mi xpath!

<List xmlns="http://schemas.microsoft.com/sharepoint/soap/"> 
<Fields> 
    <Field> 
    </Field> 
</Fields> 
</List> 

Ésta es una versión reducida de XML que se devuelve desde un servicio web de SharePoint. También tengo la siguiente xRuta:

/List/Fields/Field 

Cuando quito el xmlns de mi XML la xRuta funciona bien. Cuando está allí mi xPath no encuentra nada. ¿Hay algo que debería estar haciendo de manera diferente con mi xPath? Modificar el XML no es una opción.

+2

Uno de los muchos duplicados: http://stackoverflow.com/questions/11345/xpaths-and-default-namespaces –

+2

No, eso no es un duplicado. Esa pregunta especifica C# mientras esto es estrictamente xpath/xml. Además, su espacio de nombres no está en blanco, mientras que el mío sí. –

+0

Necesita un cierto nivel de abstracción ... Está preguntando cómo seleccionar elementos en el espacio de nombres predeterminado con una expresión XPath. ** Esta es la mayoría de las preguntas frecuentes **. –

Respuesta

71

que también tienen la siguiente xRuta:

/List/Fields/Field 

Cuando quito los xmlns de mi XML la xRuta funciona bien. Cuando está en allí mi xRuta encuentra nada

Si no se puede registrar un espacio de nombres vinculante y no puede utilizar (suponiendo que el prefijo registrada es "x"):

/x:List/x:Fields/x:Fiels 

Luego hay otro manera:

/*[name()='List']/*[name()='Fields']/*[name()='Field'] 
14

Lo más probable es que tenga que registrar ese espacio de nombres uri con su biblioteca xpath. Dependiendo de la biblioteca, puede usar el prefijo 'predeterminado' o puede necesitar darle un prefijo con nombre y usarlo en sus consultas xpath.

Por ejemplo, en PHP (ya que no se ha especificado un idioma) usando DOMXPath se podría hacer algo como esto:

$xpath = new DOMXPath($document); 
$xpath->registerNamespace('x', 'http://schemas.microsoft.com/sharepoint/soap/'); 
$xpath->query('/x:List/x:Fields/x:Field'); 
+0

Sí, soy un chico .NET y normalmente mi solución sería el equivalente .NET de eso. Desafortunadamente estamos usando un entorno de desarrollo "rápido" de terceros que no nos dará la capacidad de hacer esto ... –

+1

Además, ¿por qué incluso incluyen un espacio de nombres si no hay un prefijo? (la porción 'x:' de su xPath) –

+1

Hay un espacio de nombres. Simplemente usa el prefijo 'predeterminado' en este archivo en particular. El archivo sería semánticamente idénticos eran que '' – Anomie

35

El elemento de lista se ha definido con un nombre por defecto y esto es adoptada por todos los elementos adentro

Es, por tanto, tienen que pasar por alto el espacio de nombres de elemento de este modo:

/*[local-name()='List']/*[local-name()='Fields]/*[local-name()='Field] 

pero esto significa que el XPath se le haga ningún otro elemento de la lista - Campos - El campo

Puede hacer una verificación de espacio de nombres así como un nombre local de los registros de esta manera:

/*[local-name()='List' and namespace-uri()='http://schemas.microsoft.com/sharepoint/soap/']/*[local-name()='Fields' and namespace-uri()='http://schemas.microsoft.com/sharepoint/soap/']/*[local-name()='Field' and namespace-uri()='http://schemas.microsoft.com/sharepoint/soap/'] 

O puede registrar el espacio de nombres con la biblioteca y luego especificar explícitamente el prefijo para ese espacio de nombres y ad d es xpath expresión, el método de que depende de la biblioteca que está utilizando.

+1

Esta respuesta funciona, mientras que la respuesta aceptada no funciona ... Gracias @ zode64 por esta ayuda. Me estaba rezagando para que mi expresión xpath funcionara para el espacio de nombres incluido xml. Ahora con esto no tengo que preocuparme más por el espacio de nombres. Gracias una tonelada.. –

1

he estado teniendo este problema durante el uso de Xalan-c

El bit que no entendí al principio es que los alias/prefijos del espacio de nombres XPath o XSLT pueden ser diferentes a los del documento, dependiendo de la resolución del espacio de nombres.

Parece que si hay un espacio de nombres en el documento, no puede coincidir con un elemento de ruta a menos que se use un espacio de nombres. (estándar pero no siempre seguido?)

El XalanDocumentPrefixResolver asignará XPath o XSLT espacios de nombres de URI y tratar de darles Identificación por conseguir el prefijo - donde no hay prefijo se utiliza el nombre que se convirtió en xmlns

/xmlns:List/xmlns:Fields/xmlns:Field

alternativa, podría crear su propia resolución, pero todavía requiere un mínimo de un espacio de nombres utilizado en el XPath :(

Aquí es uno Pirateé juntos durante la prueba, no hay garantía de la memoria

// don't care what prefix given, there can only be the one 
struct NoPrefixResolver : public xalanc::PrefixResolver { 

    NoPrefixResolver(const xalanc::XalanDOMString& theURI) : m_uri(theURI){} 

    virtual const xalanc::XalanDOMString* 
     getNamespaceForPrefix(const xalanc::XalanDOMString&  prefix) const { 
     return &m_uri; 
    } 

    virtual const xalanc::XalanDOMString& getURI() const { 
     return m_uri; 
    } 

    const xalanc::XalanDOMString m_uri; 
}; 

/x:List/x:Fields/x:Field 
/a:List/b:Fields/c:Field 
-1

Si puede omitir el elemento de documento, el siguiente XPath también puede ayudar:

//Fields/Field 

Esto funciona siempre y cuando usted no tiene 'campos' por debajo de cualquier otro nodo y mientras los subnodos tienen sin espacio de nombres

Cuestiones relacionadas