2008-08-14 39 views
16

Câu chuyện đằng sau XPath và hỗ trợ cho không gian tên là gì? XPath có phải là đặc tả trước các không gian tên không? Nếu tôi có một tài liệu mà các yếu tố đã được đưa ra một không gian tên mặc định:XPATHS và không gian tên mặc định

<foo xmlns="uri" /> 

Có vẻ như một số các thư viện xử lý XPath sẽ không nhận ra //foo vì không gian tên trong khi những người khác sẽ làm. Tùy chọn nhóm của tôi đã nghĩ đến là thêm tiền tố không gian tên bằng cách sử dụng cụm từ thông dụng cho XPath (bạn có thể thêm tiền tố không gian tên thông qua XmlNameTable) nhưng điều này có vẻ dễ vỡ vì XPath là ngôn ngữ linh hoạt khi nói đến kiểm tra nút.

Có một tiêu chuẩn áp dụng cho điều này không?

Cách tiếp cận của tôi hơi bị hack nhưng dường như nó hoạt động tốt; Tôi xóa tuyên bố xmlns bằng tìm kiếm/thay thế và sau đó áp dụng XPath.

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

Đó có phải là cách tiếp cận công bằng hoặc có ai giải quyết vấn đề này khác nhau không?

Trả lời

10

Tôi đã thử một cái gì đó tương tự như những gì palehorse đề xuất và không thể làm cho nó hoạt động. Vì tôi đã nhận được dữ liệu từ một dịch vụ được xuất bản nên tôi không thể thay đổi xml.Tôi đã kết thúc bằng cách sử dụng XmlDocument và XmlNamespaceManager như vậy:

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

Nếu bạn muốn chọn sử dụng các nút ở nhiều độ sâu, bạn sẽ phải thực hiện một số việc như: 'xml.SelectNodes (" kml: kml/kml: Tài liệu/kml: Thư mục ", trình quản lý)' –

0

Nếu bạn đang cố gắng sử dụng xslt, bạn có thể thêm không gian tên vào khai báo biểu định kiểu. Nếu bạn làm điều đó, bạn phải chắc chắn rằng có một tiền tố hoặc nó sẽ không hoạt động. Nếu XML nguồn không có tiền tố, điều đó vẫn ổn, bạn thêm tiền tố của riêng bạn vào biểu định kiểu.

kiểu

<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> 

Hoặc một cái gì đó như thế.

4

Vấn đề là một phần tử không có vùng tên được khai báo là trong không gian tên NULL - do đó nếu // foo khớp với không gian tên bạn coi là 'mặc định' sẽ không có cách nào để chỉ một phần tử trong không gian tên null. Hãy nhớ rằng tiền tố cho một không gian tên chỉ là một quy ước viết tắt, tên phần tử thực (Tên đủ điều kiện, hoặc Tên viết tắt là QName) bao gồm không gian tên đầy đủ và tên địa phương. Thay đổi tiền tố cho một không gian tên không thay đổi 'danh tính' của một phần tử - nếu nó nằm trong cùng một không gian tên và cùng một tên cục bộ thì nó là cùng một loại phần tử, ngay cả khi tiền tố khác nhau.

XPath 2.0 (hay đúng hơn là XSLT 2.0) có khái niệm 'không gian tên xpath mặc định'. Bạn có thể đặt thuộc tính không gian tên xpath-default-namespace trên phần tử xsl: stylesheet.

0

Sử dụng libxml có vẻ như làm việc này:

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); 
} 
Các vấn đề liên quan