2013-02-19 73 views
2

我正在努力解決如何在當前結構化但不嚴格的XML文件的文件上使用Linq到XML。它們是格式良好的文件,但不包含XML聲明。他們實際上是SGML文件。Linq到結構化文檔上的XML查詢

目前我有:

private void Find_element_attribute_Click(object sender, EventArgs e) 
{ 
    if (comboBox2.Text != "") 
    { 
     string[] projectFiles = Directory.GetFiles(path, typeExtention, SearchOption.AllDirectories); 

     foreach (string file in projectFiles) 
     { 
      XElement root = XElement.Load(file); 
      IEnumerable<XElement> selectedElement = from el in root.Elements(Element_textBox.Text) 
        where (string)el.Attribute(Attribute_textBox.Text) == Value_textBox.Text 
        select el; //need to selct the DMC and title and put in a variable, and list them 

      foreach (XElement el in selectedElement) 
       MessageBox.Show("text" + el); 
     } 

    } 
    MessageBox.Show("Please select a project to query"); 
} 

這將引發exeption由於第二行上的一個「[」字符。該字符是文檔中實體列表的開頭括號。

我能想到做這個工作的唯一方法是添加一個XML聲明到我的文檔的開始,當我打開它們,然後使用Linq查詢文檔,然後刪除聲明。不過,我不知道如何去做這件事。任何幫助讚賞。

我的文檔的開始看起來像

<!--Arbortext, Inc., 1988-2009, v.4002--> 
<!DOCTYPE DMODULE PUBLIC "-//AECMA CSDB//DTD Air Vehicle Engines Equipment Description 19980102//EN" [ 
<!ENTITY ICN-BR8412XXXXXXX-1CX-AG30000-A-K7626-01966-A01-1 SYSTEM "ICN-BR8412XXXXXXX-1CX-AG30000-A-K7626-01966-A01-1.cgm" NDATA cgm> 
<!ENTITY ICN-BR8412XXXXXXX-1CX-AG30000-A-K7626-01964-A01-1 SYSTEM "ICN-BR8412XXXXXXX-1CX-AG30000-A-K7626-01964-A01-1.cgm" NDATA cgm> 
<!ENTITY ICN-BR8412XXXXXXX-1CX-AG30000-A-K7626-01963-A01-1 SYSTEM "ICN-BR8412XXXXXXX- 
]> 
<dmodule><idstatus> 
<dmaddres> 
<dmc><avee><modelic>XXXXXXAXXXXXX</modelic><sdc>1AX</sdc><chapnum>AG3</chapnum> 
<section>0</section><subsect>0</subsect><subject>00</subject><discode>01</discode> 
<discodev>00</discodev><incode>018</incode><incodev>A</incodev><itemloc>A 
</itemloc></avee></dmc> 
<dmtitle><techname>Equipment - INTRODUCTION</techname><infoname>Introduction 
</infoname> 
</dmtitle> 
<issno issno="001" type="new"> 
<issdate year="2012" month="11" day="30"></dmaddres> 
<status> 
<security class="3"> 
<rpc> </rpc> 
<orig> </orig> 
<applic></applic> 
<techstd> 
<autandtp> 
<authblk>Chap 1</authblk> 
<tpbase>8412(A)</tpbase> 
</autandtp> 
<authex></authex> 
<notes></notes> 
</techstd> 
<qa> 
<firstver type="tabtop"></qa> 
</status> 
</idstatus><content> 
<refs> 
<norefs></refs> 
<descript> 
<para0><title>INTRODUCTION</title> 
+2

你能提供樣本輸入嗎? – Vitaliy 2013-02-19 14:21:38

+0

你檢查了[SGMLReader](https://github.com/MindTouch/SGMLReader)嗎? – 2013-02-19 14:23:39

+0

它不需要用於讀取xml文檔的xml聲明。 – 2013-02-19 14:27:22

回答

0

在這種情況下,問題不在於它需要一個XML聲明,但是從第二行至行的內容。事實上,由於它們不是有效的XML,因此您的代碼無法解析它們。一個取巧的辦法,可以跳過線:

string content = String.Join("", File.ReadAllLines().Skip(6).ToArray()); 
MemoryStream ms = new MemoryStream(Encoding.Unicode.GetBytes(content)); 
XElement root = XElement.Load(ms); 

那麼,如果這些內容後面跟着一個有效的XML,你應該不會有什麼其他的問題,但我想,這似乎是無效的。

在這裏尋找XML 1.0 Recommendations來創建一個有效的XML文件。

+0

如果您查看您提供的鏈接,您會注意到doctype聲明可以是有效XML文檔的一部分。 – svick 2013-02-19 17:21:34

+0

是的,我知道,但在這種情況下,它似乎是無效的。 – 2013-02-19 18:40:17

0

XML解析器不抱怨,因爲您有DOCTYPE聲明,它的抱怨是因爲您有錯誤DOCTYPE聲明。 According to the XML specificationPUBLIC必須後跟兩個字符串(「PubidLiteral」和「SystemLiteral」),而不只是一個。

但我覺得沒有一點試圖修復該文件,因爲它包含的部段:

<qa> 
<firstver type="tabtop"></qa> 

有未關閉的標籤,如這是SGML(和HTML)不錯,但它不是在允許XML。因此,我認爲你不應該嘗試使用LINQ to XML來解析這個文件,因爲它確實不是XML。

但是,如果您可以使用實際上可以讀取SGML的XmlReader的實現,那麼使用LINQ to XML會很有意義。在Alex Filipovici的評論中提到的SGMLReader似乎就是這樣。