将 xml 个节点读取到数据集,编辑后代的值并保存 (Visual Studio) - 重新打开
Read xml nodes to dataset, edit values of descendants and save (Visal Studio) - reopen
这是我的 sample.xml 文件。我正在寻找如何读取此内容并将所有节点(子节点)的内容放入 DataSet 并在 DataGrid 中显示的说明。我只能读取单个节点(没有子节点)。
我的代码如下:
Private Sub ReadXmlButton_Click() Handles ReadXmlButton.Click
Dim filePath As String = "C:\Path\"
DataSet.ReadXml("C:\Path\sample.xml")
DataGridView1.DataSource = DataSet
DataGridView1.DataMember = "CART_ID"
End Sub
但它只读取没有子节点的头节点 (1000, 10.05, YES, 8, 2)。我想在 DataGridView 中显示第一个(和所有)CART_ID
的所有信息(例如:1000、10.05、A1A、Triangle、10、1、YES、8、2)。
我的结果:
预期结果:
sample.xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<XML_FILE>
<typ>xml</typ>
<ID>
<NR>007</NR>
</ID>
<PERSONAL>
<Surname>John</Surname>
<Name>Smith</Name>
</PERSONAL>
<COUNTRY>
<CName>UK</CName>
</COUNTRY>
<CITY>
<TOWN>
<TOWN_ID>
<PART_ID>
<CART_ID>
<SIMPLE_ID>1000</SIMPLE_ID>
<SIMPLE_AREA_ID>10.05</SIMPLE_AREA_ID>
<PLACE_ID>
<SPECIFIC_ID>
<id>A1A</id>
<name>Triangle</name>
<area>10</area>
<note>1</note>
</SPECIFIC_ID>
</PLACE_ID>
<Control>YES</Control>
<Control_area>8</Control_area>
<Control_rest>2</Control_rest>
</CART_ID>
<CART_ID>
<SIMPLE_ID>2000</SIMPLE_ID>
<SIMPLE_AREA_ID>20.05</SIMPLE_AREA_ID>
<PLACE_ID>
<SPECIFIC_ID>
<id>B1B</id>
<name>Triangle</name>
<area>20</area>
<note>2</note>
</SPECIFIC_ID>
</PLACE_ID>
<Control>YES</Control>
<Control_area>18</Control_area>
<Control_rest>2</Control_rest>
</CART_ID>
</PART_ID>
</TOWN_ID>
</TOWN>
</CITY>
</XML_FILE>
更新:
最后一件事是如何将修改后的后代(例如 - 手动将 SIMPPLE_ID 从 1000 更改为 5000 等)保存到原始 sample.xml 文件?是否可以使用此解决方案来实现,还是我应该寻找其他方式?
@Artec 假设三件事:
- 您的购物车节点结构是标准的
- 你知道节点的名字
- 您正在使用 Windows 表单,因为您拥有 DataGridView 控件
...而不是使用数据集,首先创建一个class,其属性对应于您需要的数据的节点
Public Class CartItem
Public Property Simple_ID As String
Public Property Simple_Area_ID As String
Public Property Place_ID As String
Public Property Place_Name As String
'...
End Class
现在在您的表单 class 上,通过 XDocument 从 xml 文件中获取数据并创建 CartItem 列表。
Public Class Form1
Private _CartItems As List(Of CartItem)
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
_CartItems = New List(Of CartItem)
'TODO: Replace ... below with your file location.
BuildCart("...\sample.xml")
DataGridView1.DataSource = _CartItems
End Sub
Private Sub BuildCart(XmlSourcePath As String)
Dim xDoc As XDocument = XDocument.Load(XmlSourcePath)
For Each cartElement As XElement In xDoc.Root.Descendants("CART_ID")
Dim item As New CartItem
With cartElement
item.Simple_Area_ID = .Descendants("SIMPLE_ID").Value
item.Simple_ID = .Descendants("SIMPLE_AREA_ID").Value
item.Place_ID = .Descendants("id").Value
item.Place_Name = .Descendants("name").Value
'...
End With
_CartItems.Add(item)
Next
End Sub
End Class
注意:有多种读取 xml 文件的方法,例如 XMLTextReader; XML文档; XPath文档;阅读器;等。使用 XDocument 只是我个人的偏好。如果您想查看其他选项,则必须进行一些研究。这完全取决于您的 xml 文件的复杂程度、您的要求和偏好。
这应该会让您朝着正确的方向前进。
@Artec 我已经很长时间没有使用 WinForms 了,我不确定是否有更简单的方法来确定更改了特定的行和列。现在,我只是寻求最简单和基本的解决方案,让您朝着正确的方向前进。
首先,由于您的 xml 结构,我们不能直接将数据集替换回 xml。无法判断代码需要深入 CART_ID 元素几层。因此,我们将反转加载 xml.
的方法
使用我之前回答中的相同 CartItem class,我们将 DataGridView 数据集转换为 CartItem 列表。使用列表的值更新 xDoc 元素并将 xDocument 保存回 xml.
Public Class Form1
Private _CartItems As List(Of CartItem)
'TODO: Replace ... with the file location.
Private _FilePath As String = "...\source.xml"
'... Button1_Click and BuildCart in here.
Private Sub UpdateXmlButton_Click(sender As Object, e As EventArgs) Handles UpdateXmlButton.Click
_CartItems = DirectCast(DataGridView1.DataSource, List(Of CartItem))
UpdateXml()
MessageBox.Show("Update Done.")
End Sub
Private Sub UpdateXml()
Dim xDoc As XDocument = XDocument.Load(_FilePath)
Dim cartIDs As IEnumerable(Of XElement) = xDoc.Root.Descendants("CART_ID")
For index As Integer = 0 To cartIDs.Count - 1
Dim cartElement As XElement = cartIDs.ElementAt(index)
Dim item As CartItem = _CartItems(index)
With cartElement
.Descendants("SIMPLE_ID").Value = item.Simple_Area_ID
.Descendants("SIMPLE_AREA_ID").Value = item.Simple_ID
.Descendants("id").Value = item.Place_ID
.Descendants("name").Value = item.Place_Name
'...
End With
Next
xDoc.Save(_FilePath)
End Sub
End Class
您实际上是在更改内存中加载的 XDocument 的元素并将其放回 xml 文件中。肯定有很多可以改进的地方,比如:
- 循环遍历属性,而不是在一行中对每个 属性 进行编码。这可以通过反射和字典的结合来实现。
- 仅更新已更改的元素而不是更改整个内容
- 等等
但上面的代码应该可以帮助您入门。
这是我的 sample.xml 文件。我正在寻找如何读取此内容并将所有节点(子节点)的内容放入 DataSet 并在 DataGrid 中显示的说明。我只能读取单个节点(没有子节点)。
我的代码如下:
Private Sub ReadXmlButton_Click() Handles ReadXmlButton.Click
Dim filePath As String = "C:\Path\"
DataSet.ReadXml("C:\Path\sample.xml")
DataGridView1.DataSource = DataSet
DataGridView1.DataMember = "CART_ID"
End Sub
但它只读取没有子节点的头节点 (1000, 10.05, YES, 8, 2)。我想在 DataGridView 中显示第一个(和所有)CART_ID
的所有信息(例如:1000、10.05、A1A、Triangle、10、1、YES、8、2)。
我的结果:
预期结果:
sample.xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<XML_FILE>
<typ>xml</typ>
<ID>
<NR>007</NR>
</ID>
<PERSONAL>
<Surname>John</Surname>
<Name>Smith</Name>
</PERSONAL>
<COUNTRY>
<CName>UK</CName>
</COUNTRY>
<CITY>
<TOWN>
<TOWN_ID>
<PART_ID>
<CART_ID>
<SIMPLE_ID>1000</SIMPLE_ID>
<SIMPLE_AREA_ID>10.05</SIMPLE_AREA_ID>
<PLACE_ID>
<SPECIFIC_ID>
<id>A1A</id>
<name>Triangle</name>
<area>10</area>
<note>1</note>
</SPECIFIC_ID>
</PLACE_ID>
<Control>YES</Control>
<Control_area>8</Control_area>
<Control_rest>2</Control_rest>
</CART_ID>
<CART_ID>
<SIMPLE_ID>2000</SIMPLE_ID>
<SIMPLE_AREA_ID>20.05</SIMPLE_AREA_ID>
<PLACE_ID>
<SPECIFIC_ID>
<id>B1B</id>
<name>Triangle</name>
<area>20</area>
<note>2</note>
</SPECIFIC_ID>
</PLACE_ID>
<Control>YES</Control>
<Control_area>18</Control_area>
<Control_rest>2</Control_rest>
</CART_ID>
</PART_ID>
</TOWN_ID>
</TOWN>
</CITY>
</XML_FILE>
更新: 最后一件事是如何将修改后的后代(例如 - 手动将 SIMPPLE_ID 从 1000 更改为 5000 等)保存到原始 sample.xml 文件?是否可以使用此解决方案来实现,还是我应该寻找其他方式?
@Artec 假设三件事:
- 您的购物车节点结构是标准的
- 你知道节点的名字
- 您正在使用 Windows 表单,因为您拥有 DataGridView 控件
...而不是使用数据集,首先创建一个class,其属性对应于您需要的数据的节点
Public Class CartItem
Public Property Simple_ID As String
Public Property Simple_Area_ID As String
Public Property Place_ID As String
Public Property Place_Name As String
'...
End Class
现在在您的表单 class 上,通过 XDocument 从 xml 文件中获取数据并创建 CartItem 列表。
Public Class Form1
Private _CartItems As List(Of CartItem)
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
_CartItems = New List(Of CartItem)
'TODO: Replace ... below with your file location.
BuildCart("...\sample.xml")
DataGridView1.DataSource = _CartItems
End Sub
Private Sub BuildCart(XmlSourcePath As String)
Dim xDoc As XDocument = XDocument.Load(XmlSourcePath)
For Each cartElement As XElement In xDoc.Root.Descendants("CART_ID")
Dim item As New CartItem
With cartElement
item.Simple_Area_ID = .Descendants("SIMPLE_ID").Value
item.Simple_ID = .Descendants("SIMPLE_AREA_ID").Value
item.Place_ID = .Descendants("id").Value
item.Place_Name = .Descendants("name").Value
'...
End With
_CartItems.Add(item)
Next
End Sub
End Class
注意:有多种读取 xml 文件的方法,例如 XMLTextReader; XML文档; XPath文档;阅读器;等。使用 XDocument 只是我个人的偏好。如果您想查看其他选项,则必须进行一些研究。这完全取决于您的 xml 文件的复杂程度、您的要求和偏好。
这应该会让您朝着正确的方向前进。
@Artec 我已经很长时间没有使用 WinForms 了,我不确定是否有更简单的方法来确定更改了特定的行和列。现在,我只是寻求最简单和基本的解决方案,让您朝着正确的方向前进。
首先,由于您的 xml 结构,我们不能直接将数据集替换回 xml。无法判断代码需要深入 CART_ID 元素几层。因此,我们将反转加载 xml.
的方法使用我之前回答中的相同 CartItem class,我们将 DataGridView 数据集转换为 CartItem 列表。使用列表的值更新 xDoc 元素并将 xDocument 保存回 xml.
Public Class Form1
Private _CartItems As List(Of CartItem)
'TODO: Replace ... with the file location.
Private _FilePath As String = "...\source.xml"
'... Button1_Click and BuildCart in here.
Private Sub UpdateXmlButton_Click(sender As Object, e As EventArgs) Handles UpdateXmlButton.Click
_CartItems = DirectCast(DataGridView1.DataSource, List(Of CartItem))
UpdateXml()
MessageBox.Show("Update Done.")
End Sub
Private Sub UpdateXml()
Dim xDoc As XDocument = XDocument.Load(_FilePath)
Dim cartIDs As IEnumerable(Of XElement) = xDoc.Root.Descendants("CART_ID")
For index As Integer = 0 To cartIDs.Count - 1
Dim cartElement As XElement = cartIDs.ElementAt(index)
Dim item As CartItem = _CartItems(index)
With cartElement
.Descendants("SIMPLE_ID").Value = item.Simple_Area_ID
.Descendants("SIMPLE_AREA_ID").Value = item.Simple_ID
.Descendants("id").Value = item.Place_ID
.Descendants("name").Value = item.Place_Name
'...
End With
Next
xDoc.Save(_FilePath)
End Sub
End Class
您实际上是在更改内存中加载的 XDocument 的元素并将其放回 xml 文件中。肯定有很多可以改进的地方,比如:
- 循环遍历属性,而不是在一行中对每个 属性 进行编码。这可以通过反射和字典的结合来实现。
- 仅更新已更改的元素而不是更改整个内容
- 等等
但上面的代码应该可以帮助您入门。