2008-08-14 9 views
16

Jaka jest historia XPath i obsługa przestrzeni nazw? Czy XPath jako specyfikacja poprzedzała przestrzenie nazw? Jeśli mam dokument gdzie elementy zostały podane domyślnej przestrzeni nazw:XPATHS i domyślne przestrzenie nazw

<foo xmlns="uri" /> 

Wydaje się, że niektóre z bibliotek procesorów XPath nie rozpozna //foo powodu nazw, podczas gdy inni będą. Opcja, o której myślał mój zespół, polega na dodaniu przedrostka przestrzeni nazw za pomocą wyrażeń regularnych do XPath (możesz dodać prefiks przestrzeni nazw za pomocą XmlNameTable), ale wydaje się, że jest to kruche, ponieważ XPath jest językiem elastycznym, jeśli chodzi o testy węzłów.

Czy istnieje jakiś standard, który się do tego stosuje?

Moje podejście jest nieco hackish, ale wydaje się działać dobrze; Usuwam deklarację xmlns za pomocą wyszukiwania/zamiany, a następnie stosuję XPath.

string readyForXpath = Regex.Replace(xmldocument, "xmlns=\".+\"", String.Empty); 

Czy to uczciwe podejście czy ktoś rozwiązał to inaczej?

Odpowiedz

10

Próbowałem czegoś podobnego do tego, co zaproponował palehorse i nie mogłem go uruchomić. Ponieważ otrzymywałem dane z opublikowanej usługi, nie mogłem zmienić xml.I skończył przy użyciu XmlDocument i XmlNamespaceManager tak:

XmlDocument doc = new XmlDocument(); 
doc.LoadXml(xmlWithBogusNamespace);    
XmlNamespaceManager nSpace = new XmlNamespaceManager(doc.NameTable); 
nSpace.AddNamespace("myNs", "http://theirUri"); 

XmlNodeList nodes = doc.SelectNodes("//myNs:NodesIWant",nSpace); 
//etc 
+0

Jeśli chcesz wybrać, używając węzłów na wielu głębokościach, musisz skończyć coś takiego: 'xml.SelectNodes (" kml: kml/kml: Document/kml: Folder ", manager)' –

0

Jeśli próbujesz użyć xslt, możesz dodać przestrzeń nazw do deklaracji arkusza stylów. Jeśli to zrobisz, musisz upewnić się, że istnieje prefiks lub nie będzie działać. Jeśli źródłowy plik XML nie ma prefiksu, to nadal jest w porządku, dodajesz własny prefiks w arkuszu stylów.

Stylesheet

<xsl:stylesheet 
    xmlns:fb="uri" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 

    <xsl:template match="fb:foo/bar"> 
     <!-- do stuff here --> 
    </xsl:template> 
</xsl:stylsheet> 

Albo coś w tym stylu.

4

Problem polega na tym, że element bez przestrzeni nazw deklarowany jest w przestrzeni nazw NULL - dlatego jeśli // foo byłby dopasowany do przestrzeni nazw, którą uznajemy za "domyślną", nie byłoby możliwości odwołania się do elementu w pusta przestrzeń nazw.

Pamiętaj również, że prefiks dla przestrzeni nazw jest tylko skrótową konwencją. Prawdziwa nazwa elementu (Qualified Name lub QName for short) składa się z pełnej przestrzeni nazw i lokalnej nazwy. Zmiana przedrostka dla przestrzeni nazw nie zmienia "tożsamości" elementu - jeśli jest w tej samej przestrzeni nazw i tej samej lokalnej nazwie, to jest to ten sam rodzaj elementu, nawet jeśli prefiks jest inny.

XPath 2.0 (a raczej XSLT 2.0) ma pojęcie "domyślnej przestrzeni nazw xpath". Możesz ustawić atrybut xpath-default-namespace na elemencie xsl: stylesheet.

0

Korzystanie libxml wydaje się to działa:

http://xmlsoft.org/examples/xpath1.c

int 
register_namespaces(xmlXPathContextPtr xpathCtx, const xmlChar* nsList) { 
    xmlChar* nsListDup; 
    xmlChar* prefix; 
    xmlChar* href; 
    xmlChar* next; 

    assert(xpathCtx); 
    assert(nsList); 

    nsListDup = xmlStrdup(nsList); 
    if(nsListDup == NULL) { 
    fprintf(stderr, "Error: unable to strdup namespaces list\n"); 
    return(-1); 
    } 

    next = nsListDup; 
    while(next != NULL) { 
    /* skip spaces */ 
    while((*next) == ' ') next++; 
    if((*next) == '\0') break; 

    /* find prefix */ 
    prefix = next; 
    next = (xmlChar*)xmlStrchr(next, '='); 
    if(next == NULL) { 
     fprintf(stderr,"Error: invalid namespaces list format\n"); 
     xmlFree(nsListDup); 
     return(-1); 
    } 
    *(next++) = '\0'; 

    /* find href */ 
    href = next; 
    next = (xmlChar*)xmlStrchr(next, ' '); 
    if(next != NULL) { 
     *(next++) = '\0'; 
    } 

    /* do register namespace */ 
    if(xmlXPathRegisterNs(xpathCtx, prefix, href) != 0) { 
     fprintf(stderr,"Error: unable to register NS with prefix=\"%s\" and href=\"%s\"\n", prefix, href); 
     xmlFree(nsListDup); 
     return(-1); 
    } 
    } 

    xmlFree(nsListDup); 
    return(0); 
} 
Powiązane problemy