2013-04-26 25 views
2

我的任務是將平靜的Web服務的結果轉換爲具有新格式的XML文檔。如何在嘗試重命名節點時忽略創建無限循環的幻影xml屬性?

的HTML/XHTML的例子轉換:

<?xml version="1.0" encoding="UTF-8"?> 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> 
    <head> 
     <title>OvidWS Result Set Resource</title> 
    </head> 
    <body> 
     <table id="results"> 
      <tr> 
       <td class="_index"> 
        <a class="uri" href="REDACTED">1</a> 
       </td> 
       <td class="au"> 
        <span>GILLESPIE JB</span> 
        <span>KUKES RE</span> 
       </td> 
       <td class="so">A.M.A. American Journal of Diseases of Children</td> 
       <td class="ti">Acetylsalicylic acid poisoning with recovery.</td> 
       <td class="ui">20267726</td> 
       <td class="yr">1947</td> 
       </tr> 
       <tr> 
       <td class="_index"> 
        <a class="uri" href="REDACTED">2</a> 
       </td> 
       <td class="au">BASS MH</td> 
       <td class="so">Journal of the Mount Sinai Hospital, New York</td> 
       <td class="ti">Aspirin poisoning in infants.</td> 
       <td class="ui">20265054</td> 
       <td class="yr">1947</td> 
       </tr> 
     </table> 
    </body> 
</html> 

理想情況下所有我想要做的就是採取一切被列爲類的屬性,使其元素名稱,在情況下,有沒有'class'屬性我只想將它標記爲一個項目。

這是我在尋找的轉換:

<results> 
    <citation> 
     <_index> 
      <uri href="REDACTED">1</uri> 
     </_index> 
     <au> 
      <item>GILLESPIE JB</item> 
      <item>KUKES RE</item> 
     </au> 
     <so>A.M.A. American Journal of Diseases of Children</so> 
     <ti>Acetylsalicylic acid poisoning with recovery.</ti> 
     <ui>20267726</ui> 
     <yr>1947</yr> 
    </citation> 
    <citation> 
     <_index> 
      <uri href="REDACTED">2</a> 
     </_index> 
     <au>BASS MH</au> 
     <so>Journal of the Mount Sinai Hospital, New York</so> 
     <ti>Aspirin poisoning in infants.</ti> 
     <ui>20265054</ui> 
     <yr>1947</yr> 
    </citation> 
</results> 

我發現了一小段代碼here,讓我重新命名一個節點:

Public Shared Function RenameNode(ByVal e As XmlNode, newName As String) As XmlNode 
     Dim doc As XmlDocument = e.OwnerDocument 
     Dim newNode As XmlNode = doc.CreateNode(e.NodeType, newName, Nothing) 
     While (e.HasChildNodes) 
      newNode.AppendChild(e.FirstChild) 
     End While 
     Dim ac As XmlAttributeCollection = e.Attributes 
     While (ac.Count > 0) 
      newNode.Attributes.Append(ac(0)) 
     End While 
     Dim parent As XmlNode = e.ParentNode 
     parent.ReplaceChild(newNode, e) 
     Return newNode 
    End Function 

但迭代時出現問題通過XmlAttributeCollection。出於某種原因,在查看其中一個td節點時,出現在源代碼中的2個屬性奇蹟般地出現:rowspan和colspan。看起來這些屬性與迭代器相混淆,因爲它們在被使用時不會像'class'屬性那樣從屬性列表中消失。相反,該屬性的值將被消耗(從「1」更改爲「」)。這導致無限循環。

我注意到,他們是類型的「XMLUnspecifiedAttribute」,但是當我修改環路檢測:

While (ac.Count > 0) And Not TypeOf (ac(0)) Is System.Xml.XmlUnspecifiedAttribute 
    newNode.Attributes.Append(ac(0)) 
End While 

我收到以下錯誤:

System.Xml.XmlUnspecifiedAttribute is not accessible in this context because it is 'friend' 

任何想法,這是爲什麼發生或如何解決它?

+1

我開始我應該用思考XSLT,但我完全不熟悉它,它是否能夠適應源文檔具有靈活字段列表的事實。總共有50個左右的可選字段可能會或可能不會出現在源代碼中,這就是爲什麼我選擇這樣做的原因。 – hobwell 2013-04-26 20:00:04

+0

要麼你以不同於我的方式來做,要麼就是你的執行有些詭異。我複製了您提供的源代碼,然後通過測試應用程序運行它,並且沒有任何問題。我甚至通過將'rowspan'和'colspan'添加到'td'標籤之一來運行它,但仍然沒有問題。我使用您提供的代碼製作了測試程序。 – 2013-05-02 14:58:18

+0

這可能是由於文檔類型(我沒有在示例中包含)。我會更新問題以包含它。謝謝參觀! – hobwell 2013-05-07 14:48:17

回答

2

我認爲你遇到的問題確實是你的doc類型聲明。

由於您正在將節點完全轉換爲其他東西,我會說你甚至不需要它,並且可以safely ignore it

由於我沒有在我的測試中包括它,然後當我將它包含在內時,xmlresolver就出問題了,我假設你在這裏肯定不需要它。

您可以通過解析器設置爲nothing忽略它:

{xml document object}.Xmlresolver = nothing 

然後你的節點和流程做你的選擇。即使是源文件中的文檔類型,我也這樣做了,但仍然沒有問題。

這裏是我用來測試的代碼:

Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load 
    Dim USEDoc As New XmlDocument 

    Dim theNameManager As System.Xml.XmlNamespaceManager = New System.Xml.XmlNamespaceManager(USEDoc.NameTable) 
    theNameManager.AddNamespace("xhtml", "http://www.w3.org/1999/xhtml") 

    USEDoc.XmlResolver = Nothing 
    USEDoc.Load("RestServ.txt") 

    renameNodes(USEDoc.SelectSingleNode("descendant::xhtml:table", theNameManager)) 

    Dim SaveDoc As New XmlDocument 
    SaveDoc.AppendChild(SaveDoc.ImportNode(USEDoc.SelectSingleNode("//results", theNameManager), True)) 

    SaveDoc.Save("RestServConv.xml") 
End Sub 

Public Function renameNodes(ByVal TopNode As XmlNode) As Boolean 
    Dim UseNode As XmlNode 

    If TopNode.Name <> "#text" Then 
     If TopNode.Name = "tr" Then 
      UseNode = RenameNode(TopNode, "citation") 
     ElseIf TopNode.Name = "table" Then 
      UseNode = RenameNode(TopNode, "results") 
      UseNode.Attributes.RemoveNamedItem("id") 
     ElseIf TopNode.Attributes.Count > 0 Then 
      For Each oAttribute As XmlAttribute In TopNode.Attributes 
       If oAttribute.Name = "class" Then 
        UseNode = RenameNode(TopNode, oAttribute.Value) 
        UseNode.Attributes.RemoveNamedItem("class") 
        Exit For 
       End If 
      Next oAttribute 
     End If 

     If UseNode IsNot Nothing Then 
      If UseNode.ChildNodes.Count > 0 Then 
       Dim x As Integer 
       For x = 0 To UseNode.ChildNodes.Count - 1 
        renameNodes(UseNode.ChildNodes(x)) 
       Next x 
      End If 
     End If 
    End If 

    Return True 
End Function 

Public Shared Function RenameNode(ByVal e As XmlNode, ByVal newName As String) As XmlNode 
    Dim doc As XmlDocument = e.OwnerDocument 
    Dim newNode As XmlNode = doc.CreateNode(e.NodeType, newName, Nothing) 
    While (e.HasChildNodes) 
     newNode.AppendChild(e.FirstChild) 
    End While 
    Dim ac As XmlAttributeCollection = e.Attributes 
    While (ac.Count > 0) 
     newNode.Attributes.Append(ac(0)) 
    End While 
    Dim parent As XmlNode = e.ParentNode 
    parent.ReplaceChild(newNode, e) 
    Return newNode 
End Function 

我你的榜樣文檔中過去了,我得到的是這樣的結果:

<results> 
    <citation> 
    <_index> 
     <uri href="REDACTED">1</uri> 
    </_index> 
    <au> 
     <span xmlns="http://www.w3.org/1999/xhtml">GILLESPIE JB</span> 
     <span xmlns="http://www.w3.org/1999/xhtml">KUKES RE</span> 
    </au> 
    <so rowspan="1" colspan="1">A.M.A. American Journal of Diseases of Children</so> 
    <ti>Acetylsalicylic acid poisoning with recovery.</ti> 
    <ui>20267726</ui> 
    <yr>1947</yr> 
    </citation> 
    <citation> 
    <_index> 
     <uri href="REDACTED">2</uri> 
    </_index> 
    <au>BASS MH</au> 
    <so>Journal of the Mount Sinai Hospital, New York</so> 
    <ti>Aspirin poisoning in infants.</ti> 
    <ui>20265054</ui> 
    <yr>1947</yr> 
    </citation> 
</results> 
+0

哇!感謝您進入這樣的細節!我將最終將其標記爲答案,但我注意到,輸出中的第一個元素現在包含rowspan和colspan,它們來自哪裏? – hobwell 2013-05-08 14:12:32

+0

因此,在閱讀您的文章後,我發現在我的代碼中,我忽略了使用XMLNamespaceManager。我添加了一個,並在初始節點選擇中使用它,並且我已經消失的問題!我仍然不明白爲什麼,但問題確實解決了。太感謝了! – hobwell 2013-05-08 14:27:13

+0

你知道我沒有注意到他們在那裏。當我試圖強迫你遇到的錯誤時,我想我會親自添加它們。除此之外,您可能看到它們的原因是DTD在屬性列表中指定了它們。 – 2013-05-08 14:39:55