2008-10-08 22 views
19

Tôi có một dự án mà tôi đang sử dụng một số HTML "sống" đặc biệt xấu và buộc nó vào một DOM XML chính thức với Gói Nhanh nhẹn HTML. Những gì tôi muốn để có thể làm là sau đó truy vấn trên này với LINQ to XML để tôi có thể cạo ra các bit tôi cần. Tôi đang sử dụng phương pháp được mô tả here để phân tích cú pháp HtmlDocument thành một XDocument, nhưng khi cố gắng truy vấn điều này, tôi không chắc chắn cách xử lý các không gian tên. Trong một tài liệu cụ HTML ban đầu đã được thực sự kém định dạng XHTML với thẻ sau:Làm cách nào để bạn xử lý các không gian tên tùy ý khi truy vấn trên LINQ tới XML?

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> 

Khi cố gắng để truy vấn từ tài liệu này dường như thuộc tính namespace đang ngăn tôi khỏi làm một cái gì đó như:

var x = xDoc.Descendants("div"); 
// returns null 

Dường như đối với các thẻ "div" này, chỉ có LocalName là "div", nhưng tên thẻ thích hợp là không gian tên cộng với "div". Tôi đã cố gắng để làm một số nghiên cứu về vấn đề không gian tên XML và có vẻ như rằng tôi có thể bỏ qua không gian tên bằng cách truy vấn theo cách này:

var x = 
    (from x in xDoc.Descendants() 
    where x.Name.LocalName == "div" 
    select x); 
// works 

Tuy nhiên, điều này có vẻ như một giải pháp khá hacky và không đề cập đúng không gian tên vấn đề. Theo tôi hiểu nó một tài liệu XML thích hợp có thể chứa nhiều không gian tên và do đó cách thích hợp để xử lý nó phải là phân tích các không gian tên mà tôi đang truy vấn theo. Có ai khác phải làm việc này không? Tôi chỉ làm cho nó phức tạp? Tôi biết rằng tôi có thể tránh tất cả điều này bằng cách chỉ gắn bó với HtmlDocument và truy vấn với XPath, nhưng tôi thà tuân theo những gì tôi biết (LINQ) nếu có thể và tôi cũng muốn biết rằng tôi không đặt mình lên cho thêm không gian tên- các vấn đề liên quan xuống đường.

Cách thích hợp để xử lý các không gian tên trong tình huống này là gì?

Trả lời

17

Sử dụng LocalName sẽ không sao. Tôi sẽ không xem xét nó một hack ở tất cả nếu bạn không quan tâm những gì namespace nó trong

Nếu bạn biết không gian tên bạn muốn và bạn muốn xác định nó, bạn có thể:.

var ns = "{http://www.w3.org/1999/xhtml}"; 
var x = xDoc.Root.Descendants(ns + "div"); 

(MSDN reference)

bạn cũng có thể có được một danh sách của tất cả các không gian tên được sử dụng trong các tài liệu:

var namespaces = (from x in xDoc.Root.DescendantsAndSelf() 
        select x.Name.Namespace).Distinct(); 

tôi cho rằng bạn có thể sử dụng để làm điều này nhưng nó không thực sự bất kỳ ít một hack:

var x = namespaces.SelectMany(ns=>xDoc.Root.Descendants(ns+"div")); 
+9

Đây là điều khó chịu nhất về API XLINQ: (. Nó sẽ được tốt đẹp để có một cách để chỉ nói với nó để bỏ qua không gian tên, hoặc ít nhất là xác định một mặc định. – MichaelGG

2

Nếu bạn biết rằng không gian tên sẽ được tuyên bố bởi các yếu tố gốc của XML, như là nhất thường là trường hợp, bạn có thể làm điều này:

var ns = xDoc.Root.Name.Namespace; 
var x = xDoc.Descendants(ns + "div"); 
Các vấn đề liên quan