2010-10-20 29 views
7

Tôi đang cố gắng phân tích cú pháp một số tài liệu XML tiêu chuẩn sử dụng lược đồ có tên là MARCXML từ nhiều nguồn khác nhau.Cách phân tích cú pháp chính xác tài liệu XML với các vùng tên tùy ý

Dưới đây là vài dòng đầu tiên của một tập tin XML ví dụ mà cần phải được xử lý ...

<?xml version="1.0" encoding="UTF-8" standalone="no" ?> 
<marc:collection xmlns:marc="http://www.loc.gov/MARC21/slim" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.loc.gov/MARC21/slim http://www.loc.gov/standards/marcxml/schema/MARC21slim.xsd"> 
    <marc:record> 
    <marc:leader>00925njm 22002777a 4500</marc:leader> 

và một không có tiền tố namespace ...

<?xml version="1.0" encoding="UTF-8" standalone="no" ?> 
<collection xmlns="http://www.loc.gov/MARC21/slim"> 
    <record> 
    <leader>01142cam 2200301 a 4500</leader> 

Điểm then chốt: để có được XPaths để giải quyết hơn nữa trong chương trình, tôi phải đi qua một thói quen regex để thêm các không gian tên vào NameTable (không thêm chúng theo mặc định). Điều này có vẻ không cần thiết đối với tôi.

Regex xmlNamespace = new Regex("xmlns:(?<PREFIX>[^=]+)=\"(?<URI>[^\"]+)\"", RegexOptions.Compiled); 

XmlDocument xmlDoc = new XmlDocument(); 
xmlDoc.LoadXml(xmlRecord); 
XmlNamespaceManager nsMgr = new XmlNamespaceManager(xmlDoc.NameTable); 

MatchCollection namespaces = xmlNamespace.Matches(xmlRecord); 
foreach (Match n in namespaces) 
{ 
    nsMgr.AddNamespace(n.Groups["PREFIX"].ToString(), n.Groups["URI"].ToString()); 
} 

Cuộc gọi XPath trông giống như thế này ...

XmlNode leaderNode = xmlDoc.SelectSingleNode(".//" + LeaderNode, nsMgr);

đâu LeaderNode là một giá trị có thể cấu hình và sẽ bằng "marc:leader" trong ví dụ đầu tiên và "leader" trong ví dụ thứ hai.

Có cách nào tốt hơn, hiệu quả hơn để thực hiện việc này không? Lưu ý: đề nghị để giải quyết điều này bằng cách sử dụng LINQ được chào đón, nhưng tôi chủ yếu muốn biết làm thế nào để giải quyết điều này bằng cách sử dụng XmlDocument.

EDIT: tôi đã tư vấn GrayWizardx và bây giờ có đoạn mã sau ...

if (LeaderNode.Contains(":")) 
{ 
    string prefix = LeaderNode.Substring(0, LeaderNode.IndexOf(':')); 
    XmlNode root = xmlDoc.FirstChild; 
    string nameSpace = root.GetNamespaceOfPrefix(prefix); 
    nsMgr.AddNamespace(prefix, nameSpace); 
} 

Bây giờ không có sự phụ thuộc thêm về Regex!

+0

Tôi đang đối mặt với gần như cùng một vấn đề chính xác. Làm thế nào để bạn hoàn thành phép thuật 'LeaderNode'? Bạn có nhận thức được loại bản ghi mà bạn đang xử lý không? –

Trả lời

2

Nếu bạn biết sẽ có một phần tử đã cho trong tài liệu (ví dụ phần tử gốc) bạn có thể thử sử dụng GetNamespaceOfPrefix.

+0

Điều này có vẻ đầy hứa hẹn. Tôi sẽ thử :) –

+0

Cách tôi hiểu không gian tên, chúng có thể được khai báo ở bất cứ đâu trong tài liệu. Bạn có thể tóm tắt phương pháp này đủ để đối phó với trường hợp chung đó không? –

+0

@Patrick M Tôi không chắc chắn phải trung thực. Sự hiểu biết của tôi là chúng phải được định nghĩa trên phần tử gốc của tài liệu, nhưng có lẽ nó có thể được thêm vào bất kỳ phần tử cha nào. Tôi havent nhìn vào điều này một lúc. – GrayWizardx

Các vấn đề liên quan