Пространство имен Xml ломает мой xpath! [дубликат]
этот вопрос уже есть ответ здесь:
у меня есть следующий XML-код:
<List xmlns="http://schemas.microsoft.com/sharepoint/soap/">
<Fields>
<Field>
</Field>
</Fields>
</List>
это уменьшенная версия XML, возвращаемая из веб-службы SharePoint. У меня также есть следующий xPath:
/List/Fields/Field
когда я удалить элемент xmlns
из моего XML xPath работает нормально. Когда он там, мой xPath ничего не находит. Есть ли что-то, что я должен делать по-другому с моим xPath? Изменение XML не является опцией.
5 ответов:
у меня также есть следующий xPath:
/List/Fields/Field
когда я удаляю xmlns из моего XML xPath работает нормально. Когда это происходит там мой xPath ничего не находит
если вы не можете зарегистрировать привязку пространства имен и не можете использовать (предполагая, что зарегистрированный префикс "x"):
/x:List/x:Fields/x:Field
тогда есть другой способ:
/*[name()='List']/*[name()='Fields']/*[name()='Field']
элемент списка был определен с пространством имен по умолчанию, и это принимается всеми элементами внутри.
поэтому вам нужно игнорировать пространство имен элементов следующим образом:
/*[local-name()='List']/*[local-name()='Fields]/*[local-name()='Field]
но это означает, что xpath заберет любой другой элемент с List-Fields-Field
вы можете сделать проверку пространства имен, а также проверку локального имени следующим образом:
/*[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/']
или вы можете зарегистрировать пространство имен в библиотеке, а затем явно указать префикс для этого пространства имен и добавьте его в выражение xpath, метод которого зависит от используемой библиотеки.
вам, скорее всего, придется зарегистрировать этот uri пространства имен в своей библиотеке xpath. В зависимости от библиотеки, вы можете использовать префикс по умолчанию, или вы можете дать ему имени префикс и использовать в запросах XPath.
например, в php (поскольку вы не указали язык) с помощью DOMXPath вы можете сделать что-то вроде этого:
$xpath = new DOMXPath($document); $xpath->registerNamespace('x', 'http://schemas.microsoft.com/sharepoint/soap/'); $xpath->query('/x:List/x:Fields/x:Field');
у меня только что была эта проблема при использовании Xalan-c
бит, который я не совсем получил изначально, заключается в том, что псевдонимы/префиксы пространства имен XPath или XSLT могут отличаться от документа - в зависимости от вашего преобразователя пространства имен.
похоже, что если в документе есть пространство имен, то он не соответствует элементу пути, если не используется пространство имен. (стандарт, но не всегда соблюдается?)
XalanDocumentPrefixResolver будет отображать XPath или XSLT пространства имен для URI и попытаться дать им идентификатор, получив префикс-где нет префикса он использовал имя, которое превратилось в xmlns
/xmlns:List/xmlns:Fields/xmlns:Field
в качестве альтернативы вы можете создать свой собственный решатель, но он по-прежнему требует минимального пространства имен, используемого в xpath :(
вот один я взломал вместе во время тестирования, нет гарантии памяти
// 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