ser - ¡Espacio de nombre Xml rompiendo mi xpath!
namespace xml c# (5)
También tengo el siguiente xPath:
/List/Fields/Field
Cuando elimino los xmlns de mi XML, xPath funciona bien. Cuando está allí mi xPath no encuentra nada
Si no puede registrar un enlace de espacio de nombre y no puede usar (suponiendo que el prefijo registrado es "x"):
/x:List/x:Fields/x:Fiels
entonces hay otra manera :
/*[name()=''List'']/*[name()=''Fields'']/*[name()=''Field'']
Esta pregunta ya tiene una respuesta aquí:
- ¿Cómo trata XPath los espacios de nombres XML? 1 respuesta
Tengo el siguiente XML:
<List xmlns="http://schemas.microsoft.com/sharepoint/soap/">
<Fields>
<Field>
</Field>
</Fields>
</List>
Esta es una versión reducida de XML que se devuelve desde un servicio web de SharePoint. También tengo el siguiente xPath:
/List/Fields/Field
Cuando elimino los xmlns
de mi XML, xPath 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.
El elemento List se ha definido con un espacio de nombre predeterminado y todos los elementos dentro de él lo adoptan.
Por lo tanto, debe ignorar el espacio de nombres del elemento así:
/*[local-name()=''List'']/*[local-name()=''Fields]/*[local-name()=''Field]
pero esto significa que el xpath recogerá cualquier otro elemento con List - Fields - Field
Puede hacer una verificación de espacio de nombre así como una verificación de nombre local así:
/*[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 agregarlo a la expresión xpath, cuyo método depende de la biblioteca que esté utilizando.
He estado teniendo este problema mientras uso Xalan-c
El bit que no entendí del todo 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?)
XalanDocumentPrefixResolver asignará espacios de nombres XPath o XSLT a URI e intentará darles id obteniendo el prefijo, donde no hay prefijo, utilizó el nombre que se convirtió en xmlns
/xmlns:List/xmlns:Fields/xmlns:Field
De forma alternativa, podría crear su propia resolución, pero aún así requiere un espacio de nombre mínimo utilizado en xpath :(
Aquí hay uno que pirateé mientras probaba, sin garantía de 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
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 especificaste un idioma) usando DOMXPath podrías 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'');
Si puede omitir el elemento del documento, el siguiente XPath también puede ayudar:
//Fields/Field
Esto funciona siempre que no tenga ''Campos'' debajo de ningún otro nodo y mientras los nodos secundarios no tengan espacio de nombre.