2016-10-19 5 views
0

私はXMLデータに基づいてクラスを構築するコードジェネレータを持っています。それはデータをまっすぐに更新します。例えば、私はちょうど構造を表示する機能の大部分を省略。XMLファイルを書くためのコードを生成する最良の方法

Public Class RecordsNode 
    Inherits XmlClassBase 


    Private _current As RecordsItem 
    Private _errors As List(Of String) 
    Private _orphans As Dictionary(Of String, List(Of XmlClassBase)) 


    Public Class BandNode 
     Inherits XmlClassBase 


     Private _current As BandItem 
     Private _list As BandItem() 


     Public Class AlbumNode 
      Inherits XmlClassBase 


      Private _current As AlbumItem 
      Private _list As AlbumItem() 


      Public Class DateNode 
       Inherits XmlClassBase 


       Private _current As DateItem 
       Private _list As DateItem() 



       Public Sub New() 

        _current = New DateItem(0) 

       End Sub 


       Public Overrides ReadOnly Property Attributes As Dictionary(Of String, String) 
        Get 
         Return _current.Attributes 
        End Get 
       End Property 

       Public ReadOnly Property Current As DateItem 
        Get 
         Return _current 
        End Get 
       End Property 

       Public ReadOnly Property List As DateItem() 
        Get 
         Return _list 
        End Get 
       End Property 

       Public Overrides Property Text As String 
        Get 
         Return _current.Text 
        End Get 
        Set(value As String) 
         _current.Text = value 
        End Set 
       End Property 


       Public Overrides Sub Add() 

        If _list IsNot Nothing Then 
         ReDim Preserve _list(_list.GetUpperBound(0) + 1) 
        Else 
         ReDim _list(0) 
        End If 


        _current = New DateItem(_list.GetUpperBound(0)) 
        _list(_list.GetUpperBound(0)) = _current 

       End Sub 


       Public Function HasChildren() As Boolean 

        Return False 

       End Function 

      End Class 

      Public Class DateItem 

       Private _attributes As Dictionary(Of String, String) 
       Private _deleted As Boolean 
       Private _index As Integer 
       Private _text As String 


       Public Sub New(Index As Integer) 

        _index = Index 
       End Sub 

       Public ReadOnly Property Attributes As Dictionary(Of String, String) 
        Get 
         If _attributes Is Nothing Then 
          _attributes = New Dictionary(Of String, String) 
         End If 
         Return _attributes 
        End Get 
       End Property 

       Public ReadOnly Property ListIndex As Integer 
        Get 
         Return _index 
        End Get 
       End Property 

       Public Property Text As String 
        Get 
         Return _text 
        End Get 
        Set(value As String) 
         _text = value 
        End Set 
       End Property 

      End Class 



      Public Sub New() 

       _current = New AlbumItem(0) 

      End Sub 


      Public Overrides ReadOnly Property Attributes As Dictionary(Of String, String) 
       Get 
        Return _current.Attributes 
       End Get 
      End Property 

      Public ReadOnly Property Current As AlbumItem 
       Get 
        Return _current 
       End Get 
      End Property 

      Public ReadOnly Property List As AlbumItem() 
       Get 
        Return _list 
       End Get 
      End Property 

      Public Overrides Property Text As String 
       Get 
        Return _current.Text 
       End Get 
       Set(value As String) 
        _current.Text = value 
       End Set 
      End Property 


      Public ReadOnly Property Date As DateNode 
       Get 
        Return _current.Date 
       End Get 
      End Property 


      Public Overrides Sub Add() 

       If _list IsNot Nothing Then 
        ReDim Preserve _list(_list.GetUpperBound(0) + 1) 
       Else 
        ReDim _list(0) 
       End If 


       _current = New AlbumItem(_list.GetUpperBound(0)) 
       _list(_list.GetUpperBound(0)) = _current 

      End Sub 


      Public Function HasChildren() As Boolean 

       Return False 

      End Function 

     End Class 

     Public Class AlbumItem 

      Private _attributes As Dictionary(Of String, String) 
      Private _deleted As Boolean 
      Private _index As Integer 
      Private _text As String 
      Private _Date As AlbumNode.DateNode 



      Public Sub New(Index As Integer) 

       _index = Index 
       _Date = New AlbumNode.DateNode 


      End Sub 

      Public ReadOnly Property Attributes As Dictionary(Of String, String) 
       Get 
        If _attributes Is Nothing Then 
         _attributes = New Dictionary(Of String, String) 
        End If 
        Return _attributes 
       End Get 
      End Property 

      Public ReadOnly Property ListIndex As Integer 
       Get 
        Return _index 
       End Get 
      End Property 

      Public Property Text As String 
       Get 
        Return _text 
       End Get 
       Set(value As String) 
        _text = value 
       End Set 
      End Property 

      Public ReadOnly Property Date As AlbumNode.DateNode 
       Get 
        Return _Date 
       End Get 
      End Property 


     End Class 



     Public Sub New() 

      _current = New BandItem(0) 

     End Sub 


     Public Overrides ReadOnly Property Attributes As Dictionary(Of String, String) 
      Get 
       Return _current.Attributes 
      End Get 
     End Property 

     Public ReadOnly Property Current As BandItem 
      Get 
       Return _current 
      End Get 
     End Property 

     Public ReadOnly Property List As BandItem() 
      Get 
       Return _list 
      End Get 
     End Property 

     Public Overrides Property Text As String 
      Get 
       Return _current.Text 
      End Get 
      Set(value As String) 
       _current.Text = value 
      End Set 
     End Property 


     Public ReadOnly Property Album As AlbumNode 
      Get 
       Return _current.Album 
      End Get 
     End Property 


     Public Overrides Sub Add() 

      If _list IsNot Nothing Then 
       ReDim Preserve _list(_list.GetUpperBound(0) + 1) 
      Else 
       ReDim _list(0) 
      End If 


      _current = New BandItem(_list.GetUpperBound(0)) 
      _list(_list.GetUpperBound(0)) = _current 

     End Sub 


     Public Function HasChildren() As Boolean 

      Dim Children As Boolean 



      Return Children 

     End Function 

    End Class 

    Public Class BandItem 

     Private _attributes As Dictionary(Of String, String) 
     Private _deleted As Boolean 
     Private _index As Integer 
     Private _text As String 
     Private _Album As BandNode.AlbumNode 



     Public Sub New(Index As Integer) 

      _index = Index 
      _Album = New BandNode.AlbumNode 


     End Sub 

     Public ReadOnly Property Attributes As Dictionary(Of String, String) 
      Get 
       If _attributes Is Nothing Then 
        _attributes = New Dictionary(Of String, String) 
       End If 
       Return _attributes 
      End Get 
     End Property 

     Public ReadOnly Property ListIndex As Integer 
      Get 
       Return _index 
      End Get 
     End Property 

     Public Property Text As String 
      Get 
       Return _text 
      End Get 
      Set(value As String) 
       _text = value 
      End Set 
     End Property 

     Public ReadOnly Property Album As BandNode.AlbumNode 
      Get 
       Return _Album 
      End Get 
     End Property 


    End Class 

    Private _FilePath As String 


    Public Sub New() 

     _current = New RecordsItem(0) 
     _errors = New List(Of String) 
     _orphans = New Dictionary(Of String, List(Of XmlClassBase)) 

    End Sub 


    Public Overrides ReadOnly Property Attributes As Dictionary(Of String, String) 
     Get 
      Return _current.Attributes 
     End Get 
    End Property 

    Public ReadOnly Property Current As RecordsItem 
     Get 
      Return _current 
     End Get 
    End Property 

    Public ReadOnly Property Errors As List(Of String) 
     Get 
      Return _errors 
     End Get 
    End Property 

    Public Property FilePath As String 
     Get 
      Return _FilePath 
     End Get 
     Set 
      _FilePath = value 
     End Set 
    End Property 
    Public ReadOnly Property OrphanNodes As Dictionary(Of String, List(Of XmlClassBase)) 
     Get 
      Return _orphans 
     End Get 
    End Property 

    Public Overrides Property Text As String 
     Get 
      Return _current.Text 
     End Get 
     Set(value As String) 
      _current.Text = value 
     End Set 
    End Property 


    Public ReadOnly Property Band As BandNode 
     Get 
      Return _current.Band 
     End Get 
    End Property 

    Public Function Load() As Boolean 

     Dim Doc As xmldocument 
     Dim Node As XmlNode = Nothing 
     Dim r As Integer 


     Doc = New XmlDocument() 
     Doc.Load(_FilePath) 

     For Each Node In Doc.ChildNodes 
      If Node.Name <> "xml" Then 'Ignore any declarations. 
       Exit For 'Only 1 root node allowed, any others are ignored. 
      End If 
     Next 

     If Node.Attributes IsNot Nothing AndAlso Node.Attributes.Count > 0 Then 
      For r = 0 To Node.Attributes.Count - 1 
       Attributes.Add(Node.Attributes(r).Name, Node.Attributes(r).InnerText) 
      Next 
     End If 

     LoadChildren(Node, String.Empty, Me) 

     Return True 

    End Function 

    Public Function LoadChildren(xmlCurrent As XmlNode, ParentText As String, Parent As XmlClassBase) As XmlNode 

     Dim xmlNodeText As XmlNode 
     Dim Destination As XmlClassBase 
     Dim r As Integer 
     Dim strText As String 


     For Each xmlChildNode As XmlNode In xmlCurrent.ChildNodes 

      If xmlChildNode.NodeType = XmlNodeType.Element Then 

       Try 
        Destination = DirectCast(CallByName(Parent, xmlChildNode.Name, CallType.Get), XmlClassBase) 
       Catch mme As MissingMemberException 
        _errors.Add(mme.Message) 
        Destination = New XmlClassBase 
        AddOrphan(xmlChildNode.Name, Destination) 
       Catch ex As Exception 
        _errors.Add(ex.Message) 
        Throw 
       End Try 

       If Destination IsNot Nothing Then 
        If Destination.GetType.ToString <> "Records.XmlClassBase" Then 
         Destination.Add() 
        End If 

        strText = String.Empty 

        For Each xmlNodeText In xmlChildNode 
         If xmlNodeText.NodeType = XmlNodeType.Text Then 
          strText &= xmlNodeText.InnerText.Trim 
         End If 
        Next 

        If strText <> String.Empty Then 
         Destination.Text = strText 
        End If 

        If xmlChildNode.Attributes IsNot Nothing AndAlso xmlChildNode.Attributes.Count > 0 Then 
         For r = 0 To xmlChildNode.Attributes.Count - 1 
          Destination.Attributes.Add(xmlChildNode.Attributes(r).Name, xmlChildNode.Attributes(r).InnerText) 
         Next 
        End If 

        If xmlChildNode.HasChildNodes Then 
         LoadChildren(xmlChildNode, xmlChildNode.Name, Destination) 
        End If 

       End If 

      End If 

     Next 

     Return xmlCurrent 

    End Function 

End Class 

Public Class RecordsItem 

    Private _attributes As Dictionary(Of String, String) 
    Private _deleted As Boolean 
    Private _index As Integer 
    Private _text As String 
    Private _Band As RecordsNode.BandNode 



    Public Sub New(Index As Integer) 

     _index = Index 
     _Band = New RecordsNode.BandNode 


    End Sub 

    Public ReadOnly Property Attributes As Dictionary(Of String, String) 
     Get 
      If _attributes Is Nothing Then 
       _attributes = New Dictionary(Of String, String) 
      End If 
      Return _attributes 
     End Get 
    End Property 

    Public ReadOnly Property ListIndex As Integer 
     Get 
      Return _index 
     End Get 
    End Property 

    Public Property Text As String 
     Get 
      Return _text 
     End Get 
     Set(value As String) 
      _text = value 
     End Set 
    End Property 

    Public ReadOnly Property Band As RecordsNode.BandNode 
     Get 
      Return _Band 
     End Get 
    End Property 


End Class 

Loadメソッドは、できるだけ多くの作品(それは、これらに類似するクラスを作成します。私はこのXML

<?xml version="1.0" encoding="utf-8"?> 
<Records> 
    <Band>Black Sabbath 
     <Album> 
      Paranoid 
      <Date>1977</Date> 
     </Album> 
    </Band> 
    <Band>Iron Maiden 
     <Album> 
      Killers 
      <Date>1981</Date> 
     </Album> 
     <Album> 
      PeiceOfMind 
      <Date>1983</Date> 
     </Album> 
    </Band> 
</Records> 

を持っていると言いますxmlElementsはコンピュータが扱うことができるので、私はそれが好きで簡潔ですが好きです。私の問題は、Saveメソッドでは、何が最善の方法であるかわからない。私はRecordsNodeの下にすべてのクラスを取得し、 。

私はこのような何かを使用することができますAssembly.GetExecutin gAssembly.GetTypes()しかし、hbowでは、RecordsNodeの子ではないすべてのクラスをフィルタリングしますか?

xmlはかなり大きい場合があります。私はちょっと気になる代わりに各クラスのコードを追加することができます。それは最も安全で醜いアプローチかもしれません。

その他のオプションはありますか?このクラスは顧客によって使用される可能性があるので、私はその宛先作業環境について何も保証することはできません。

ありがとうございました。

+0

これは、C#とは何かを持っていないようだ、まだ私は 'を参照してくださいC# 'タグがあります。 – itsme86

+0

ここで何をしようとしていますか(オブジェクトデータをテキストとして保存する)は、シリアル化と呼ばれるものです。 .NETにはXmlSerializerクラスが用意されています。 https://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlserializer(v=vs.110).aspx –

+0

@Eric - 私はそれを見ました。その問題は、XMLを使ったSTARTです。そのクラスはオブジェクトで始まります。私は、シリアライズされた出力が元のXMLと一致するという信念はほとんどありません。 – John

答えて

0

ほとんどの作業をより簡単に行うXmlSerializerがあります。だからあなたのデータと、そのクラスを埋める、その後、xsd.exeを使用してXMLからクラスを作成し、その後にそのようなオブジェクトをシリアル化:

var o = new MyXmlObject(); 
//add data to your object 
//... 
XmlSerializer xs = new XmlSerializer(typeof(MyXmlObject)); 

StringWriter sw = new StringWriter(); 
using(XmlWriter xw = XmlWriter.Create(sw)) 
{ 
    xs.Serialize(xw, o); 
    using(StreamWriter sw = new StreamWriter("filepath")) 
     sw.Write(sw.ToString()); 
} 
+0

実際、Visual Studio 2015では、XSDステップは必要ありません。 XMLをコピーし、.csファイルを開き、[形式を選択して貼り付け] - > [XML to Classes]をクリックします。クラスファイルが生成されるはずです。 JSONでも動作します。典型的にはそれはかなりまともです。 – PMV

+0

私はxsdを試しました。生成されるクラスはひどいです。私はBatchPatientDataRequisitionDataResultDataRequisitionErrorListRequisitionErrorのようなクラス名で終わります。申し訳ありませんが、私は顧客にそのようなコードを与えることはできません。 – John

+0

特殊ペーストは、xsdと同じライブラリを使用します。受け入れられない(私の標準のためにとにかく)クラスを作成します。 – John

関連する問題