webentwicklung-frage-antwort-db.com.de

XML-Namespace, der meinen xpath bricht!

Ich habe folgendes XML:

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

Dies ist eine abgespeckte Version von XML, die von einem SharePoint-Webdienst zurückgegeben wird. Ich habe auch den folgenden xPath:

/List/Fields/Field

Wenn ich das xmlns aus meinem XML entferne, funktioniert der xPath einwandfrei. Wenn es drin ist, findet mein xPath nichts. Gibt es etwas, das ich mit meinem xPath anders machen sollte? Das Ändern der XML ist keine Option.

80
Abe Miessler

Ich habe auch den folgenden xPath:

/List/Fields/Field 

Wenn ich die xmlns aus meinem XML entferne, funktioniert der xPath einwandfrei. Wenn es drin ist, findet mein xPath nichts

Wenn Sie keine Namespace-Bindung registrieren und nicht verwenden können (unter der Annahme, dass das registrierte Präfix "x" ist):

/x:List/x:Fields/x:Field

dann gibt es einen anderen Weg:

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

Das List-Element wurde mit einem Standard-Namespace definiert, der von allen darin enthaltenen Elementen übernommen wird.

Sie müssen daher den Elementnamensraum wie folgt ignorieren:

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

dies bedeutet jedoch, dass der xpath jedes andere Element mit List - Fields - Field aufnimmt

Sie können eine Namespace-Prüfung sowie eine Prüfung des lokalen Namens wie folgt durchführen:

/*[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/']

Sie können den Namespace auch in der Bibliothek registrieren und dann das Präfix für diesen Namespace explizit angeben und es dem xpath-Ausdruck hinzufügen, dessen Methode von der verwendeten Bibliothek abhängt.

44
rogermushroom

Höchstwahrscheinlich müssen Sie diesen Namespace uri in Ihrer xpath-Bibliothek registrieren. Abhängig von der Bibliothek können Sie möglicherweise das Standardpräfix verwenden, oder Sie müssen ihm ein benanntes Präfix zuweisen und dieses in Ihren xpath-Abfragen verwenden.

In PHP (da Sie keine Sprache angegeben haben) mit DOMXPath können Sie beispielsweise Folgendes tun:

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

Ich hatte dieses Problem gerade, als ich Xalan-c verwendete

Das, was ich anfangs nicht ganz verstanden habe, ist, dass die XPath- oder XSLT-Namespace-Aliase/-Präfixe sich von denen des Dokuments unterscheiden können - abhängig von Ihrem Namespace-Resolver.

Wenn im Dokument ein Namespace vorhanden ist, stimmt dieser anscheinend nicht mit einem Pfadelement überein, es sei denn, es wird ein Namespace verwendet. (Standard aber nicht immer befolgt?)

Der XalanDocumentPrefixResolver ordnet URI XPath- oder XSLT-Namespaces zu und versucht, ihnen eine ID zuzuweisen, indem er das Präfix abruft. Wenn kein Präfix vorhanden ist, wird der Name verwendet, der in xmlns umgewandelt wurde

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

Alternativ können Sie auch einen eigenen Resolver erstellen, der jedoch einen minimalen Namespace im xpath benötigt :(

Hier ist eine, die ich beim Testen zusammen gehackt habe, keine Garantie für den Speicher

// 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
Greg Domjan