2009-04-20 6 views
10

Yêu cầu cơ bản của tôi là lấy giá trị phần tử từ tệp XML, tôi đã sử dụng XMLDoxument.SelectSingleNode. Tệp XML của tôi chứa một số không gian tên trong tiêu đề, vì vậy tôi đã sử dụng NameSpaceManager để thêm tiền tố không gian tên và tôi đã sử dụng tiền tố để nhận phần tử cụ thể đó. Bây giờ trong các tệp XML của tôi mà không gian tên đang nhận được khác nhau, tôi không muốn làm bất kỳ mã hóa cứng, là có cách nào mà tôi có thể tìm ra tất cả các không gian tên và tôi có thể thêm nó vào NameSpaceManager.làm thế nào tôi có thể liệt kê ra tất cả các không gian tên trong XML?

Cảm ơn.

+0

@Ruchita: Vấn đề với cách tiếp cận này là khai báo không gian tên có thể được ghi đè (trong khai báo không gian tên mặc định XML 1.0 cũng có thể được đặt lại, trong XML 1.1 tất cả các khai báo không gian tên) –

Trả lời

2

Vấn đề cơ bản của bạn khi truy xuất các không gian tên từ XmlDocument có thể được giải quyết bằng cách truy xuất NameTable của XmlDocument và tạo một XmlNameSpaceManager từ nó.

Tuy nhiên, nếu bạn muốn liệt kê các không gian tên cho một số mục đích khác, bạn nên kiểm tra phương pháp GetNamespacesInScope được hiển thị bởi lớp XmlNamespaceManager cũng như lớp XPathNavigator.

Khi sử dụng một XmlDocument, bạn có thể nhận được một XmlNamespaceManager từ nó qua đoạn mã sau:

//Instantiate an XmlDocument object. 
XmlDocument xmldoc = new XmlDocument(); 

//Load XML file into the XmlDocument object. 
xmldoc.Load("C:\\myFile.xml"); 

//Instantiate an XmlNamespaceManager object. 
XmlNamespaceManager nsMgr = new XmlNamespaceManager(xmldoc.NameTable); 

// Retrieve the namespaces into a Generic dictionary with string keys. 
IDictionary<string, string> dic = nsMgr.GetNamespacesInScope(XmlNamespaceScope.All); 

// Iterate through the dictionary. 

... 

In this article, Scott Hanselman trình bày một cách để sử dụng phương pháp này để liệt kê tất cả không gian tên trong một tài liệu sử dụng một XPathNavigator và sử dụng cầu LINQ.

+2

Điều này dường như không hiệu quả đối với tôi. Có rất nhiều mục trong NameTable của tài liệu, nhưng một số không gian tên được định nghĩa trong phần đầu của tài liệu sẽ không được thêm vào XmlNamespaceManager. Tôi tiếp tục nhận được "Không gian tên không được xác định" trong các cuộc gọi SelectNodes của tôi, trừ khi tôi thêm các không gian tên theo cách thủ công cho người quản lý. Tôi cần một giải pháp đọc chính xác các không gian tên được định nghĩa trong tài liệu XML và thêm chúng vào trình quản lý không gian tên của tôi vì vậy tôi không phải mã hóa chúng một cách chính xác. –

+0

@SeanWorle Hơi trễ một chút, nhưng hãy kiểm tra [Lấy các không gian tên từ một Tài liệu XML với XPathDocument và LINQ to XML] (http://www.hanselman.com/blog/CommentView.aspx?guid=51861b63-526f-4572- ba84-2f24a1c7bd83), có lẽ nó có thể giúp bạn hoặc người khác. – ErikE

+1

Vấn đề với cách tiếp cận này là nó bỏ qua các mục "xmlns". –

7

Cảm ơn bạn đã phản hồi nhanh ...

Tôi nghĩ phiên bản .Net bạn đang sử dụng phải là phiên bản mới nhất. Tôi đang sử dụng .Net framework 1.1 ... khá cũ :(..

Bởi thời điểm đó ,, tôi đã có một số mẫu mã như thế này .. cho cùng một mục đích ...

XmlNodeList _xmlNameSpaceList = _xmlDocument.SelectNodes(@"//namespace::*[not(. = ../../namespace::*)]"); 

      _xmlNSmgr = new XmlNamespaceManager(_xmlDocument.NameTable);   

      foreach(XmlNode nsNode in _xmlNameSpaceList) 
      { 
       _xmlNSmgr.AddNamespace(nsNode.LocalName,nsNode.Value); 
      } 

Bất kỳ nhận xét sẽ được đánh giá cao để thêm kiến ​​thức vào KB của tôi ... Cảm ơn

+0

XPath cũ tốt, hoạt động hoàn toàn tốt, nó lấy tất cả các nút có không gian tên. cảm ơn – zulucoda

-2

Nếu bạn đang tìm kiếm một cách nhanh chóng để tránh vấn đề không gian tên, hãy tách các định nghĩa vùng tên ra khỏi Xml qua RegEx trước khi bạn thực hiện XmlDocument .LoadXml (bla) Tôi thực hiện điều này khi phân tích các trang XHTML trực tiếp. Hãy tải thời gian tải XmlDoc từ 15 giây xuống còn 15 giây và làm cho nó không phải tiền tố xpath của tôi .

13

Không gian tên có thể được tìm thấy ở bất kỳ đâu trong tài liệu xml. Vì vậy, để trích xuất tất cả các không gian tên và khai báo chúng thành một XmlNamespaceManager tôi đã làm như sau:

public static XmlNamespaceManager getAllNamespaces(XmlDocument xDoc) 
{ 
    XmlNamespaceManager result = new XmlNamespaceManager(xDoc.NameTable); 

    IDictionary<string, string> localNamespaces = null; 
    XPathNavigator xNav = xDoc.CreateNavigator(); 
    while (xNav.MoveToFollowing(XPathNodeType.Element)) 
    { 
     localNamespaces = xNav.GetNamespacesInScope(XmlNamespaceScope.Local); 
     foreach (var localNamespace in localNamespaces) 
     { 
      string prefix = localNamespace.Key; 
      if (string.IsNullOrEmpty(prefix)) 
        prefix = "DEFAULT"; 

      result.AddNamespace(prefix, localNamespace.Value); 
     } 
    } 

    return result; 
} 

Chỉ cần chú ý đến trường hợp không gian tên mặc định. Tôi định nghĩa lại không gian tên mặc định là tiền tố "DEFAULT" vì tôi gặp vấn đề khi tạo SelectSingleNode bằng cách sử dụng trình quản lý không gian tên trả về ở trên khi truy vấn không gian tên mặc định. Tôi là cách giải quyết của tôi. Hy vọng điều này sẽ giúp

0

Ruchita đã đăng giải pháp làm việc cho XmlDocument. Nhưng tôi muốn làm tương tự với XDocument. Dưới đây là rất giống với XDocument:

var xml = XDocument.Load(filename); 
var xmlNameSpaceList = ((IEnumerable)xml.XPathEvaluate(@"//namespace::*[not(. = ../../namespace::*)]")).Cast<XAttribute>(); 
var xmlNSmgr = new XmlNamespaceManager(new NameTable()); 
foreach (var nsNode in xmlNameSpaceList) 
{ 
    xmlNSmgr.AddNamespace(nsNode.Name.LocalName, nsNode.Value); 
} 

Bây giờ bạn có thể sử dụng XPath với không gian tên, ví dụ: xml.XPathEvaluate("//test:p", xmlNSmgr).