Maciej Los
Существует несколько способов загрузки XML-данных, используя:
1) XmlDocument[^]
2) XDocument[^]
3) XmlSerialization[^] => Примеры сериализации XML | Microsoft Docs[^]
[РЕДАКТИРОВАТЬ]
Как я упоминал ранее, вы можете использовать класса XDocument используется для чтения данных в DataSet
объект. Это идея:
Function LoadDataIntoDataSet() As DataSet
Dim xNamespace As XNamespace = "http://www.sap.com/SBO/DIS"
Dim xDoc As XDocument = XDocument.Parse(GetXmlData())
Dim ds As DataSet = New DataSet()
Dim pl As DataTable = New DataTable()
pl.Columns.Add(New DataColumn("LineNumber", Type.GetType("System.Int32")))
Dim bn As DataTable = New DataTable()
bn.Columns.Add(New DataColumn("LineNumber", Type.GetType("System.Int32")))
bn.Columns.Add(New DataColumn("BatchNumber", Type.GetType("System.Int32")))
bn.Columns.Add(New DataColumn("Quantity", Type.GetType("System.String")))
bn.Columns.Add(New DataColumn("BaseLineNumber", Type.GetType("System.Int32")))
For Each pol As XElement In xDoc.Descendants(xNamespace + "ProductionOrderLine")
pl.Rows.Add(New Object(){pol.Element(xNamespace + "LineNumber").Value})
For Each ban As XElement In pol.Descendants(xNamespace + "BatchNumber").Where(Function(x) x.Descendants.Count>0)
bn.Rows.Add(New Object() _
{ _
pol.Element(xNamespace + "LineNumber").Value, _
ban.Element(xNamespace + "BatchNumber").Value, _
ban.Element(xNamespace + "Quantity").Value, _
ban.Element(xNamespace + "BaseLineNumber").Value _
})
Next
Next
ds.Tables.Add(pl)
ds.Tables.Add(bn)
Return ds
End Function
Но я бы настоятельно рекомендовал использовать сериализацию (через
Класс DataContractSerializer (System.Runtime.Сериализация) | Microsoft Docs[
^]). В этом случае вам понадобится набор определений классов:
'needs fererence to System.Runtime.Serialization.dll
<DataContract([Namespace] := "http://www.sap.com/SBO/DIS")>
Public Class ProductionOrder
<DataMember>
Public AbsoluteEntry As Integer
<DataMember>
Public ProductionOrderLines As List(Of ProductionOrderLine)
End Class
<DataContract>
Public Class ProductionOrderLine
<DataMember>
Public LineNumber As Integer
<DataMember>
Public BatchNumbers As List(Of BatchNumber)
End Class
<DataContract>
Public Class BatchNumber
<DataMember>
Public BatchNumber As Integer
<DataMember>
Public Quantity As String
<DataMember>
Public BaseLineNumber As Integer
End Class
Затем вы сможете конвертировать xml-данные в объекты:
'this method you'll need only first time!!!
Dim sFileName As String = "FullFileName.xml"
Dim xDoc As XDocument = XDocument.Load(sFileName)
Dim xns As XNamespace = "http://www.sap.com/SBO/DIS"
Dim po As ProductionOrder = New ProductionOrder()
po.AbsoluteEntry = xDoc.Root.Element(xns + "AbsoluteEntry").Value
po.ProductionOrderLines = New List(Of ProductionOrderLine)
For Each pol As XElement In xDoc.Descendants(xns + "ProductionOrderLine")
Dim pl As ProductionOrderLine = New ProductionOrderLine()
pl.LineNumber = pol.Element(xns + "LineNumber").Value
pl.BatchNumbers = New List(Of BatchNumber)
For Each ban As XElement In pol.Descendants(xns + "BatchNumber").Where(Function(x) x.Descendants.Count>0)
Dim bn As BatchNumber = New BatchNumber()
With bn
.BatchNumber = ban.Element(xns + "BatchNumber").Value
.Quantity = ban.Element(xns + "Quantity").Value
.BaseLineNumber = ban.Element(xns + "BaseLineNumber").Value
End With
pl.BatchNumbers.Add(bn)
Next
po.ProductionOrderLines.Add(pl)
Next
'now you can write your objects into proper way:
WriteObject(sFileName, po)
'read it again:
po = ReadObject(sFileName)
'gotcha!
Методы для чтения/записи объекта:
Sub WriteObject(_fileName As String, po As ProductionOrder)
Using writer As FileStream = New FileStream(_fileName, FileMode.Create)
Dim knownTypes() AS Type = New Type() {GetType(ProductionOrder), GetType(ProductionOrder), GetType(BatchNumber) }
Dim dcs As DataContractSerializer = New DataContractSerializer(GetType(ProductionOrder), knownTypes)
dcs.WriteObject(writer, po)
writer.Close()
End Using
End Sub
Function ReadObject(_fileName As String) As ProductionOrder
Dim po As ProductionOrder = New ProductionOrder()
Using fs As FileStream = New FileStream(_fileName, FileMode.Open)
Dim reader As XmlDictionaryReader = XmlDictionaryReader.CreateTextReader(fs, New XmlDictionaryReaderQuotas())
Dim knownTypes() AS Type = New Type() {GetType(ProductionOrder), GetType(ProductionOrder), GetType(BatchNumber) }
Dim dcs As DataContractSerializer = New DataContractSerializer(GetType(ProductionOrder), knownTypes)
po = DirectCast(dcs.ReadObject(reader, True), ProductionOrder)
reader.Close()
fs.Close()
End Using
Return po
End Function
Именно так вы можете работать с xml-данными и пользовательскими объектами!
MaReBo
Спасибо за ваше решение! Все 3 предложенных способа приводят к одному и тому же результату: элементы в XML-документах, имена которых не являются уникальными, игнорируются при загрузке в dataset-object. Я думаю, что мне придется редактировать XML-файл вручную, чтобы переименовать определенные узлы. Попытался избежать этого обходного пути.
MaReBo
Спасибо! Я думаю, что это сработает, и я попробую это для моего класса производственного заказа. Требуется немного времени, чтобы проработать это, но в конце концов это будет стабильное решение.