2011-07-07 80 views
6

我正在解析來自第三方提供者的一些XML文件,但不幸的是,它並不總是格式良好的XML,因爲有時某些元素包含重複屬性。如何使用C刪除XML中的重複屬性#

我沒有控制源,我不知道哪些元素可能具有重複的屬性,也不知道事先重複的屬性名稱。

顯然,內容加載到XMLDocument對象會在重複一個XmlException屬性,所以我雖然我可以用一個XmlReader通過元素步驟雖然XML元素和處理,當我到達出錯的元素的重複屬性。

但是,XmlException是在reader.Read()上提出的 - 在我有機會忽略元素的屬性之前。

下面就來演示這個問題的樣品的方法:

public static void ParseTest() 
{ 
    const string xmlString = 
     @"<?xml version='1.0'?> 
     <!-- This is a sample XML document --> 
     <Items dupattr=""10"" id=""20"" dupattr=""33""> 
      <Item>test with a child element <more/> stuff</Item> 
     </Items>"; 

    var output = new StringBuilder(); 
    using (XmlReader reader = XmlReader.Create(new StringReader(xmlString))) 
    { 
     XmlWriterSettings ws = new XmlWriterSettings(); 
     ws.Indent = true; 
     using (XmlWriter writer = XmlWriter.Create(output, ws)) 
     { 
      while (reader.Read()) /* Exception throw here when Items element encountered */ 
      { 
       switch (reader.NodeType) 
       { 
        case XmlNodeType.Element: 
         writer.WriteStartElement(reader.Name); 
         if (reader.HasAttributes){ /* CopyNonDuplicateAttributes(); */} 
         break; 
        case XmlNodeType.Text: 
         writer.WriteString(reader.Value); 
         break; 
        case XmlNodeType.XmlDeclaration: 
        case XmlNodeType.ProcessingInstruction: 
         writer.WriteProcessingInstruction(reader.Name, reader.Value); 
         break; 
        case XmlNodeType.Comment: 
         writer.WriteComment(reader.Value); 
         break; 
        case XmlNodeType.EndElement: 
         writer.WriteFullEndElement(); 
         break; 
       } 
      } 

     } 
    } 
    string str = output.ToString(); 
} 

有另一種方式來解析輸入並刪除重複的屬性,而不必使用正則表達式和字符串操作?

+0

只有在XML處理器API提供程序有任何鉤子的情況下才允許你掛鉤處理並處理錯誤條件 – Ankur

+0

有趣的問題,期待看到解決方案! –

+2

使用XML將無法解決此問題,因爲您的輸入不是XML。你說你無法控制輸入,但是你至少可以讓你的上級知道你的供應商沒有給你發送XML嗎?你至少可以確保你的_vendor_知道這一點嗎?任何愚蠢地發送這些數據的組織都可能愚蠢到沒有意識到它不是XML。 –

回答

3

我發現一個解決方案,將XML視爲一個HTML文檔。然後使用開源的Html Agility Pack庫,我能夠獲得有效的XML。

訣竅是先保存帶有HTML標頭的xml。
所以與HTML聲明這樣的替換XML聲明
<?xml version="1.0" encoding="utf-8" ?>

!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

一旦內容保存到文件中,此方法將返回一個有效的XML文檔。

// Requires reference to HtmlAgilityPack 
public XmlDocument LoadHtmlAsXml(string url) 
{ 
    var web = new HtmlWeb(); 

    var m = new MemoryStream(); 
    var xtw = new XmlTextWriter(m, null); 

    // Load the content into the writer 
    web.LoadHtmlAsXml(url, xtw); 

    // Rewind the memory stream 
    m.Position = 0; 

    // Create, fill, and return the xml document 
    XmlDocument xmlDoc = new XmlDocument(); 
    xmlDoc.LoadXml((new StreamReader(m)).ReadToEnd()); 
    return xmlDoc; 
} 

重複的屬性節點與後來的屬性值覆蓋早期的自動刪除

0

好吧認爲你需要捕獲錯誤:

那麼你應該能夠使用以下方法:

reader.MoveToFirstAttribute(); 

reader.MoveToNextAttribute() 

得到以下特性:

reader.Value 
reader.Name 

這將使您能夠獲取所有屬性值。

+0

我可以捕獲錯誤並處理當前節點上的屬性(即複製非重複項),但問題仍然是繼續處理文檔的其餘部分,因爲'reader.Read()'返回false,因此不再處理元素。 – Catch22

+0

#Catch22,是的,我確實遇到過,而試圖讓代碼恢復。我希望你能找到解決辦法。看看這裏:http://bytes.com/topic/c-sharp/answers/827965-how-handle-xml-parsing-exception它看起來像XMLReader是不容錯誤的原因。這通常是個好消息,但就你的情況而言,這意味着我建議的解決方案可能不起作用。抱歉 – openshac