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 не является вариантом.

Ответ 1

У меня также есть следующий xPath:

/List/Fields/Field 

Когда я удаляю xmlns из своего XML xPath отлично работает. Когда он там мой xPath ничего не находит

Если вы не можете зарегистрировать привязку пространства имен и не можете использовать (при условии, что зарегистрированный префикс "x" ):

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

, тогда есть другой способ:

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

Ответ 2

Элемент List был определен с пространством имен по умолчанию, и это принимается всеми элементами внутри.

Поэтому вам нужно игнорировать пространство имен элементов следующим образом:

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

но это означает, что xpath возьмет любой другой элемент со списком - Поля - Поле

Вы можете выполнить проверку пространства имен, а также проверку локального имени так:

/*[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, метод которого зависит от используемой библиотеки.

Ответ 3

Вам, скорее всего, придется зарегистрировать это пространство имен 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');

Ответ 4

У меня была эта проблема при использовании 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 

Ответ 5

Если вы можете пропустить элемент документа, следующий XPath также может помочь:

//Fields/Field

Это работает до тех пор, пока у вас нет "полей" ниже любого другого node, и до тех пор, пока узлы не имеют пространства имен.