我必须创建一个XML文档,以便在其他软件中进行导入。无法修改导入过程,因此xml及其结构是固定的。
我在visualstudio中使用VB.net。我使用“ Xml.Serialization.XmlSerializer”,过去对我来说效果很好。
对于这个主题,我通常使用“ xml修饰符”将整个xml结构作为类“重建”:
Public Class Xyz
<xmlattribute> property id as integer
<xmlelement> property name as string
<xmlelement> property comment as string
<xmlelement> property block as string
<xmlelement> property test as List(of Test)
Public Sub New()
test = new List(of Test)
End Sub
End Class
Public Class Test
<xmlelement> property name as string
End Class
然后我得到这样的xml部分:
<Xyz id=0>
<Name>Abc</Name>
<Comment>Abc</Comment>
<Block>Abc</Block>
<Test>
<Name>Abc</Name>
</Test>
<Test>
<Name>Def</Name>
</Test>
<Test>
<Name>Ghi</Name>
</Test>
</Xyz>
但是现在我在xml中有两个问题,我需要任何人的启发。首先,“块”具有直接值(如之前)和诸如“ id_block”的属性。其次,“ Test”元素上有一个序列号。导入必须看起来像这样:
<Xyz id=0>
<Name>Abc</Name>
<Comment>Abc</Comment>
<Block id_Block=5>Abc</Block>
<Test_0>
<Name>Abc</Name>
</Test_0>
<Test_1>
<Name>Def</Name>
</Test_1>
<Test_2>
<Name>Ghi</Name>
</Test_2>
</Xyz>
我如何实现这两个主题?
使用Xml Linq:
Imports System.Xml
Imports System.Xml.Linq
Module Module1
Const FILENAME As String = "c:\temp\test.xml"
Sub Main()
Dim doc As XDocument = XDocument.Load(FILENAME)
Dim xyz As Xyz = doc.Descendants("Xyz").Select(Function(x) New Xyz With { _
.id = CType(x.Attribute("id"), Integer), _
.name = CType(x.Element("Name"), String), _
.comment = CType(x.Element("Comment"), String), _
.block = CType(x.Element("Block"), String), _
.test = x.Elements().Where(Function(y) y.Name.LocalName.StartsWith("Test")).Select(Function(y) CType(y.Element("Name"), String)).ToList()
}).FirstOrDefault()
End Sub
End Module
Public Class Xyz
Property id As Integer
Property name As String
Property comment As String
Property block As String
Property test As List(Of String)
End Class
您在下面看到的我的解决方案。它对我有用,但是...
我不明白,为什么我需要在父级使用IXMLSERIALIZER而在(索引)子级使用IXMLSERIALIZER。我进行了其他测试,但是没有用。每次都是里面的“ test”标签,而不仅仅是“ test_1”标签。该解决方案或其他/更好的解决方案有什么好的解释?
我的代码:
Public Class Xyz
Inherits IndexedParent
<XmlAttribute> Property id As Integer
<XmlElement> Property name As String
<XmlElement> Property comment As String
<XmlElement> Property block As String
<XmlIgnore> Property test As List(Of Test)
<XmlIgnore> Property tryNext As List(Of TryNext)
Public Sub New()
test = New List(Of Test)
tryNext = New List(Of TryNext)
RegisterIndexedChildList(test)
RegisterIndexedChildList(tryNext)
End Sub
End Class
Public Class Test
Inherits IndexedChild
<XmlElement> Property Name As String
<XmlElement> Property Name2 As String
End Class
Public Class TryNext
Inherits IndexedChild
<XmlElement> Property N As String
<XmlElement> Property N2 As String
End Class
Public MustInherit Class IndexedParent
Implements IXmlSerializable
Private registeredChildLists As List(Of IEnumerable(Of IndexedChild))
Public Sub RegisterIndexedChildList(pChildList As IEnumerable(Of IndexedChild))
If registeredChildLists Is Nothing Then
registeredChildLists = New List(Of IEnumerable(Of IndexedChild))
End If
registeredChildLists.Add(pChildList)
End Sub
Public Function GetSchema() As XmlSchema Implements IXmlSerializable.GetSchema
Return Nothing
End Function
Public Sub ReadXml(reader As XmlReader) Implements IXmlSerializable.ReadXml
Throw New NotImplementedException()
End Sub
Public Sub WriteXml(writer As XmlWriter) Implements IXmlSerializable.WriteXml
IndexedChild.WritePropertiesAsXml(writer, Me)
For Each childList As IEnumerable(Of IndexedChild) In registeredChildLists
IndexedChild.WriteAllXmlElements(writer, childList)
Next
End Sub
End Class
Public MustInherit Class IndexedChild
Implements IXmlSerializable
Public Shared Function WriteAllXmlElements(pWriter As XmlWriter, pList As IEnumerable(Of IndexedChild))
For Each item As IXmlSerializable In pList
pWriter.WriteStartElement(item.GetType.Name.ToString.ToLower + pList.ToList.IndexOf(item).ToString)
item.WriteXml(pWriter)
pWriter.WriteEndElement()
Next
End Function
Public Shared Function WritePropertiesAsXml(pWriter As XmlWriter, pObj As Object)
For Each prop As Reflection.PropertyInfo In pObj.GetType().GetProperties
If Attribute.IsDefined(prop, GetType(XmlElementAttribute)) Then
pWriter.WriteElementString(prop.Name, prop.GetValue(pObj, Nothing))
ElseIf Attribute.IsDefined(prop, GetType(XmlAttributeAttribute)) Then
pWriter.WriteAttributeString(prop.Name, prop.GetValue(pObj, Nothing))
End If
Next
End Function
Public Sub ReadXml(reader As XmlReader) Implements IXmlSerializable.ReadXml
Throw New NotImplementedException
End Sub
Public Sub WriteXml(writer As XmlWriter) Implements IXmlSerializable.WriteXml
WritePropertiesAsXml(writer, Me)
End Sub
Public Function GetSchema() As XmlSchema Implements IXmlSerializable.GetSchema
Return Nothing
End Function
End Class