小鋪上的一個詢問【多層的xml 如何解析】,對方傳來一個多層的xml,要如何解析他並將他轉換成GridView顯示出來,小喵順便把過程整理成文章,以便未來有類似需求的朋友可以參考。
緣起
小鋪上的一個詢問【多層的xml 如何解析】,對方傳來一個多層的xml,要如何解析他並將他轉換成GridView顯示出來,小喵順便把過程整理成文章,以便未來有類似需求的朋友可以參考。
XML格式務必正確
其實解析XML的方式很多,透過XmlDocument,Linq to Xml, Xml轉物件,都是可行的方式。不過,很重要的一點
Xml的格式一定要正確
Xml的格式一定要正確
Xml的格式一定要正確
(因為很重要,所以講三次)
Xml的格式一旦有問題,那麼不管哪種Xml衍生出來的方式都無效,只能當作純文字去處理他
該篇的11樓,樓主提供的格式有問題,MedlineCitation 這個標籤有頭無尾,無法收尾就無法處理,所以小喵先行整理Xml,讓Xml格是正確變成可以去解析的內容。
<?xml version="1.0"?>
<!DOCTYPE PDArticleSet PUBLIC "-//NLM//DTD PDArticle, 1st January 2014//EN" "http://www.ncbi.nlm.nih.gov/corehtml/query/DTD/PD_140101.dtd">
<PDArticleSet>
<PDArticle>
<MedlineCitation Owner="NLM" Status="PD-not-MEDLINE">
<PMID Version="1">1</PMID>
<DateCreated>
<Year>2014</Year>
<Month>08</Month>
<Day>11</Day>
</DateCreated>
<DateCompleted>
<Year>2014</Year>
<Month>08</Month>
<Day>11</Day>
</DateCompleted>
</MedlineCitation>
</PDArticle>
<PDArticle>
<MedlineCitation Owner="NLM" Status="PD-not-MEDLINE">
<PMID Version="1">2</PMID>
<DateCreated>
<Year>2014</Year>
<Month>08</Month>
<Day>11</Day>
</DateCreated>
<DateCompleted>
<Year>2014</Year>
<Month>08</Month>
<Day>11</Day>
</DateCompleted>
</MedlineCitation>
</PDArticle>
</PDArticleSet>
有了正確的Xml,剩下的就挑一種解決的方式。
剛好前幾天友分享一篇【[筆記] Object 物件(集合) XML 互轉 公用程式】,就利用這篇的方式將Xml轉為物件,之後再進行處理
選擇性貼上→貼上 XML 做為類別
Visual Studio不愧是地表最強的開發工具,提供將xml轉為物件類別的方式,使用方式很簡單,只需要新增一個類別檔,別管一開始的內容,將正確格式的Xml複製下來,接著,到類別編輯區的空白處,點選【功能表】的【編輯】→【選擇性貼上】→【貼上XML做為類別】,神奇的,XML對應的類別就產生好了
當然,相關的資料他會依據貼上的範例內容,去判斷該用什麼樣的資料型態,不過產生的型態不見的合適,這時候可以針對產生的形態稍做調整一下
於是就產生好類別,針對一些欄位的型態,稍微做調整後,類別內容如下:
Imports Microsoft.VisualBasic
'''<remarks/>
<System.Xml.Serialization.XmlTypeAttribute(AnonymousType:=True), _
System.Xml.Serialization.XmlRootAttribute([Namespace]:="", IsNullable:=False)> _
Partial Public Class PDArticleSet
Private pDArticleField() As PDArticleSetPDArticle
'''<remarks/>
<System.Xml.Serialization.XmlElementAttribute("PDArticle")> _
Public Property PDArticle() As PDArticleSetPDArticle()
Get
Return Me.pDArticleField
End Get
Set(value As PDArticleSetPDArticle())
Me.pDArticleField = Value
End Set
End Property
End Class
'''<remarks/>
<System.Xml.Serialization.XmlTypeAttribute(AnonymousType:=True)> _
Partial Public Class PDArticleSetPDArticle
Private medlineCitationField As PDArticleSetPDArticleMedlineCitation
'''<remarks/>
Public Property MedlineCitation() As PDArticleSetPDArticleMedlineCitation
Get
Return Me.medlineCitationField
End Get
Set(value As PDArticleSetPDArticleMedlineCitation)
Me.medlineCitationField = Value
End Set
End Property
End Class
'''<remarks/>
<System.Xml.Serialization.XmlTypeAttribute(AnonymousType:=True)> _
Partial Public Class PDArticleSetPDArticleMedlineCitation
Private pMIDField As PDArticleSetPDArticleMedlineCitationPMID
Private dateCreatedField As PDArticleSetPDArticleMedlineCitationDateCreated
Private dateCompletedField As PDArticleSetPDArticleMedlineCitationDateCompleted
Private ownerField As String
Private statusField As String
'''<remarks/>
Public Property PMID() As PDArticleSetPDArticleMedlineCitationPMID
Get
Return Me.pMIDField
End Get
Set(value As PDArticleSetPDArticleMedlineCitationPMID)
Me.pMIDField = Value
End Set
End Property
'''<remarks/>
Public Property DateCreated() As PDArticleSetPDArticleMedlineCitationDateCreated
Get
Return Me.dateCreatedField
End Get
Set(value As PDArticleSetPDArticleMedlineCitationDateCreated)
Me.dateCreatedField = Value
End Set
End Property
'''<remarks/>
Public Property DateCompleted() As PDArticleSetPDArticleMedlineCitationDateCompleted
Get
Return Me.dateCompletedField
End Get
Set(value As PDArticleSetPDArticleMedlineCitationDateCompleted)
Me.dateCompletedField = Value
End Set
End Property
'''<remarks/>
<System.Xml.Serialization.XmlAttributeAttribute()> _
Public Property Owner() As String
Get
Return Me.ownerField
End Get
Set(value As String)
Me.ownerField = Value
End Set
End Property
'''<remarks/>
<System.Xml.Serialization.XmlAttributeAttribute()> _
Public Property Status() As String
Get
Return Me.statusField
End Get
Set(value As String)
Me.statusField = Value
End Set
End Property
End Class
'''<remarks/>
<System.Xml.Serialization.XmlTypeAttribute(AnonymousType:=True)> _
Partial Public Class PDArticleSetPDArticleMedlineCitationPMID
Private versionField As Integer
Private valueField As Integer
'''<remarks/>
<System.Xml.Serialization.XmlAttributeAttribute()> _
Public Property Version() As Integer
Get
Return Me.versionField
End Get
Set(value As Integer)
Me.versionField = value
End Set
End Property
'''<remarks/>
<System.Xml.Serialization.XmlTextAttribute()> _
Public Property Value() As Integer
Get
Return Me.valueField
End Get
Set(value As Integer)
Me.valueField = value
End Set
End Property
End Class
'''<remarks/>
<System.Xml.Serialization.XmlTypeAttribute(AnonymousType:=True)> _
Partial Public Class PDArticleSetPDArticleMedlineCitationDateCreated
Private yearField As String
Private monthField As String
Private dayField As String
'''<remarks/>
Public Property Year() As String
Get
Return Me.yearField
End Get
Set(value As String)
Me.yearField = value
End Set
End Property
'''<remarks/>
Public Property Month() As String
Get
Return Me.monthField
End Get
Set(value As String)
Me.monthField = value
End Set
End Property
'''<remarks/>
Public Property Day() As String
Get
Return Me.dayField
End Get
Set(value As String)
Me.dayField = value
End Set
End Property
End Class
'''<remarks/>
<System.Xml.Serialization.XmlTypeAttribute(AnonymousType:=True)> _
Partial Public Class PDArticleSetPDArticleMedlineCitationDateCompleted
Private yearField As String
Private monthField As String
Private dayField As String
'''<remarks/>
Public Property Year() As String
Get
Return Me.yearField
End Get
Set(value As String)
Me.yearField = value
End Set
End Property
'''<remarks/>
Public Property Month() As String
Get
Return Me.monthField
End Get
Set(value As String)
Me.monthField = value
End Set
End Property
'''<remarks/>
Public Property Day() As String
Get
Return Me.dayField
End Get
Set(value As String)
Me.dayField = value
End Set
End Property
End Class
建立GridView顯示要使用的類別
由於最後希望藉由 GridView 來顯示資料,所以另外定一個類別,用來搭配GridView顯示資料用,相關的內容如下:
Public Class PDArticleInfo
Public Property PMID As Integer = 0
Public Property DateCreate As Date = Nothing
Public Property DateCCompleted As Date = Nothing
End Class
到此,準備工作差不多完成了,接著就是來實際的使用測試看看
測試
小喵準備一個TextBox,用來貼上Xml,這樣可以反覆的來進行測試,一個按鈕來啟動轉換,一個GridView來顯示最後的結果
於是安排畫面如下:
<asp:TextBox ID="txtXml" runat="server" TextMode="MultiLine" Rows="20" Columns="50"></asp:TextBox>
<br />
<asp:Button ID="Button1" runat="server" Text="Button" />
<br />
<asp:GridView ID="GridView1" runat="server">
</asp:GridView>
接著,撰寫按鈕按下後的相關動作
Protected Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
'如果內容不是空的
If Me.txtXml.Text <> "" Then
'轉換公用程式的物件初始化
Dim oUtilO2X As New UtilObj2Xml
'宣告轉換完成的物件
Dim oPDASet As PDArticleSet
'透過公用程式進行物件轉換
oPDASet = oUtilO2X.Xml2Obj(GetType(PDArticleSet), Me.txtXml.Text)
'宣告給GridView顯示的物件集合
Dim oPDAs As New List(Of PDArticleInfo)
'物件集合中的單一物件宣告
Dim tPDA As PDArticleInfo
'迴圈將xml轉換的物件取出,放入GridView要顯示的物件集合中
For Each m As PDArticleSetPDArticle In oPDASet.PDArticle
tPDA = New PDArticleInfo
tPDA.PMID = m.MedlineCitation.PMID.Value
tPDA.DateCreate = CDate(m.MedlineCitation.DateCreated.Year & "/" & m.MedlineCitation.DateCreated.Month & "/" & m.MedlineCitation.DateCreated.Day)
tPDA.DateCCompleted = CDate(m.MedlineCitation.DateCompleted.Year & "/" & m.MedlineCitation.DateCompleted.Month & "/" & m.MedlineCitation.DateCompleted.Day)
oPDAs.Add(tPDA)
Next
'將物件集合設定為GridView的DataSource並綁定
Me.GridView1.DataSource = oPDAs
Me.GridView1.DataBind()
End If
End Sub
就醬子,測試結果如下:
末記
類似的需求,無論Xml來自哪裡,只要他的內容格式是正確的,就可以透過以上的方式去處理他。JSON 的資料其實也是方式類似的做法。這樣的方式可以應用在政府的公開資料(Open Data)只要是他的格是正確,我們就可以透過以上類似的步驟來進行,而且不只運用在WebForm,用MVC,Windows Form, Windows Phone等,都可以套用。
相關方式記錄一下,提供大家參考
^_^
以下是簽名:
- 歡迎轉貼本站的文章,不過請在貼文主旨上加上【轉貼】,並在文章中附上本篇的超連結與站名【topcat姍舞之間的極度凝聚】,感恩大家的配合。
- 小喵大部分的文章會以小喵熟悉的語言VB.NET撰寫,如果您需要C#的Code,也許您可以試著用線上的工具進行轉換,這裡提供幾個參考
Microsoft MVP Visual Studio and Development Technologies (2005~2019/6) | topcat Blog:http://www.dotblogs.com.tw/topcat |