如何使用c#读取xml文件子节点下同名的多个标签

本文关键字:标签 子节点 何使用 读取 xml 文件 | 更新日期: 2023-09-27 18:16:19

对于下面的xml我想读取所有行节点值,因为你可以看到有子类别标签下的多个行标签,所以对于特定的子类别(假设子类别ID="标准")我想获取所有行标签?如何使用c#做到这一点?

<DPS>
  <Category ID="Handsets">
    <Device ID="Samsung">
      <Contract ID="twoFour">
        <Tariff ID="Standard4G">
          <SubCategory ID="Standard">
            <Row>
              <Minutes>"Minutes":"999999"</Minutes>
              <Texts>"Texts":"99999"</Texts>
              <Data>"Data":"10000"</Data>
              <Content>"Content":"No"</Content>
              <Roaming>"Roaming":"Y + 2000"</Roaming>
              <Monthly>"Monthly":"38"</Monthly>
              <Upfront>"Upfront":0"</Upfront>
            </Row>
            <Row>
              <Minutes>Minutes:999</Minutes>
              <Texts>Texts:99994569</Texts>
              <Data>Data:100</Data>
              <Content>Content:No</Content>
              <Roaming>Roaming:Y + 2000</Roaming>
              <Monthly>Monthly:398</Monthly>
              <Upfront>Upfront:0</Upfront>
            </Row>
            <Row>
              <Minutes>Minutes:99</Minutes>
              <Texts>Texts:92569</Texts>
              <Data>Data:10</Data>
              <Content>Content:No</Content>
              <Roaming>Roaming:Y + 2000</Roaming>
              <Monthly>Monthly:38</Monthly>
              <Upfront>Upfront:0</Upfront>
            </Row>
          </SubCategory>
          <SubCategory ID="RedValue">
            <Row>
              <Minutes>"Minutes":"999999"</Minutes>
              <Texts>"Texts":"99999"</Texts>
              <Data>"Data":"10000"</Data>
              <Content>"Content":"No"</Content>
              <Roaming>"Roaming":"Y + 2000"</Roaming>
              <Monthly>"Monthly":"38"</Monthly>
              <Upfront>"Upfront":0"</Upfront>
            </Row>
            <Row>
              <Minutes>Minutes:999</Minutes>
              <Texts>Texts:99994569</Texts>
              <Data>Data:100</Data>
              <Content>Content:No</Content>
              <Roaming>Roaming:Y + 2000</Roaming>
              <Monthly>Monthly:398</Monthly>
              <Upfront>Upfront:0</Upfront>
            </Row>
            <Row>
              <Minutes>Minutes:99</Minutes>
              <Texts>Texts:92569</Texts>
              <Data>Data:10</Data>
              <Content>Content:No</Content>
              <Roaming>Roaming:Y + 2000</Roaming>
              <Monthly>Monthly:38</Monthly>
              <Upfront>Upfront:0</Upfront>
            </Row>
          </SubCategory>
        </Tariff>
      </Contract>
    </Device>
  </Category>
</DPS>

如何使用c#读取xml文件子节点下同名的多个标签

首先,将XML加载到XDocument中。

var xdoc = XDocument.Parse(xml); // Or XDocument.Load(pathToXmlFile), etc....

然后,您可以查询所有子类别元素的ID为"标准",最后询问它的所有子元素,行。

var rows = xdoc.Descendants("SubCategory")
  .Where(sc => sc.Attribute("ID").Value == "Standard")
  .Elements();

Edit:要从上述XML中获取实际值,这是一种方法。

我编写了一个内联函数,根据名称从行中获取给定的元素,并处理从中剥离不需要的字符。

Func<XElement, string, string> getElementValue = (XElement row, string name)
    => row.Element(name).Value
        .Split(':').Last() // Take only the right side of the colons
        .Trim('"'); // Remove the double quotes, if any

然后,我们可以使用它来获取每行所需的所有属性:

var rowData = rows.Select(x => new {
    Minutes = getElementValue(x, "Minutes"),
    Texts = getElementValue(x, "Texts"),
    Data = getElementValue(x, "Data"),
    Content = getElementValue(x, "Content"),
    Roaming = getElementValue(x, "Roaming"),
    Monthly = getElementValue(x, "Monthly"),
    Upfront = getElementValue(x, "Upfront")
});

对于实际使用,你可能会想要创建一个类的属性,如Minutes, Texts等,如果你还没有定义,然后把类名后的new关键字,行被选中。

Edit 2:对于每个元素中被确认为"输入错误"的额外文本位,您可以完全跳过内联函数并将rowData选择简化为:

var rowData = rows.Select(x => new {
    Minutes = x.Element("Minutes").Value,
    Texts = x.Element("Texts").Value,
    Data = x.Element("Data").Value,
    Content = x.Element("Content").Value,
    Roaming = x.Element("Roaming").Value,
    Monthly = x.Element("Monthly").Value,
    Upfront = x.Element("Upfront").Value
});

此VB代码无法使用我可以访问的转换器转换为c#。我知道XML文本在c#中没有对应的文本,但是除了一些测试数据之外,其他任何东西都不需要。

由于XML看起来结构良好,所以我创建了一系列模拟数据的类。它们只是一个起点,因为我不知道数据的来龙去脉。

让我们从最后开始查看Standard中的每一行。添加了调试以帮助可视化

    Dim myDPS As New DPS(xe)
    myDPS.Category.Device.Tariff.SubCategory.GetOnePart("Standard")
    Debug.WriteLine(myDPS.Category.Device.Tariff.SubCategory.OnePart.ToString)
    For Each el As XElement In myDPS.Category.Device.Tariff.SubCategory.Row.OnePart.Elements
        Debug.WriteLine(el.ToString)
    Next

这些是类。

Public Class DPS : Inherits DPSBaseClass
    Public Category As DPSCategory
    Public Sub New(path As String)
        MyBase.New(XElement.Load(path))
    End Sub
    Public Sub New(element As XElement)
        MyBase.New(element)
        If Me.OnePart IsNot Nothing Then
            Me.Category = New DPSCategory(Me.OnePart)
        End If
    End Sub
End Class
Public Class DPSCategory : Inherits DPSBaseClass
    Public Device As DPSDevice
    Public Sub New(element As XElement)
        MyBase.New(element)
        If Me.OnePart IsNot Nothing Then
            Me.Device = New DPSDevice(Me.OnePart)
        End If
    End Sub
End Class
Public Class DPSDevice : Inherits DPSBaseClass
    Public Tariff As DPSTariff
    Public Sub New(element As XElement)
        MyBase.New(element)
        If Me.OnePart IsNot Nothing Then
            Me.Tariff = New DPSTariff(Me.OnePart)
        End If
    End Sub
End Class
Public Class DPSTariff : Inherits DPSBaseClass
    Public SubCategory As DPSSubCategory
    Public Sub New(element As XElement)
        MyBase.New(element)
        If Me.OnePart IsNot Nothing Then
            Me.SubCategory = New DPSSubCategory(Me.OnePart)
        End If
    End Sub
End Class
Public Class DPSSubCategory : Inherits DPSBaseClass
    Public Row As DPSSubCategoryRow
    Public Sub New(element As XElement)
        MyBase.New(element)
        If Me.OnePart IsNot Nothing Then
            Me.Row = New DPSSubCategoryRow(Me.OnePart)
        End If
    End Sub
End Class
Public Class DPSSubCategoryRow : Inherits DPSBaseClass
    Public Sub New(element As XElement)
        MyBase.New(element)
    End Sub
End Class
Public MustInherit Class DPSBaseClass
    Private TheData As XElement
    Private DataParts As New List(Of XElement)
    Public OnePart As XElement
    Public Sub New(path As String)
        Me.New(XElement.Load(path))
    End Sub
    Public Sub New(element As XElement)
        Me.TheData = element
        Me.GetDataParts()
    End Sub
    Public Sub GetDataParts()
        Me.DataParts = (From el In Me.TheData.Elements Select el).ToList
        Me.GetOnePart("")
    End Sub
    Public Sub GetOnePart(ID As String)
        If Me.DataParts.Count > 0 Then
            If ID <> "" Then
                Me.OnePart = (From el In Me.DataParts Where el.@ID = ID Select el Take 1).FirstOrDefault
            Else
                Me.OnePart = Me.DataParts.FirstOrDefault
            End If
        End If
    End Sub
End Class

这是用来测试

的烦人的XML文字
    Dim xe As XElement = <DPS>
                             <Category ID="Handsets">
                                 <Device ID="Samsung">
                                     <Contract ID="twoFour">
                                         <Tariff ID="Standard4G">
                                             <SubCategory ID="Standard">
                                                 <Row>
                                                     <Minutes>"Minutes":"999999"</Minutes>
                                                     <Texts>"Texts":"99999"</Texts>
                                                     <Data>"Data":"10000"</Data>
                                                     <Content>"Content":"No"</Content>
                                                     <Roaming>"Roaming":"Y + 2000"</Roaming>
                                                     <Monthly>"Monthly":"38"</Monthly>
                                                     <Upfront>"Upfront":0"</Upfront>
                                                 </Row>
                                                 <Row>
                                                     <Minutes>Minutes:999</Minutes>
                                                     <Texts>Texts:99994569</Texts>
                                                     <Data>Data:100</Data>
                                                     <Content>Content:No</Content>
                                                     <Roaming>Roaming:Y + 2000</Roaming>
                                                     <Monthly>Monthly:398</Monthly>
                                                     <Upfront>Upfront:0</Upfront>
                                                 </Row>
                                                 <Row>
                                                     <Minutes>Minutes:99</Minutes>
                                                     <Texts>Texts:92569</Texts>
                                                     <Data>Data:10</Data>
                                                     <Content>Content:No</Content>
                                                     <Roaming>Roaming:Y + 2000</Roaming>
                                                     <Monthly>Monthly:38</Monthly>
                                                     <Upfront>Upfront:0</Upfront>
                                                 </Row>
                                             </SubCategory>
                                             <SubCategory ID="RedValue">
                                                 <Row>
                                                     <Minutes>"Minutes":"999999"</Minutes>
                                                     <Texts>"Texts":"99999"</Texts>
                                                     <Data>"Data":"10000"</Data>
                                                     <Content>"Content":"No"</Content>
                                                     <Roaming>"Roaming":"Y + 2000"</Roaming>
                                                     <Monthly>"Monthly":"38"</Monthly>
                                                     <Upfront>"Upfront":0"</Upfront>
                                                 </Row>
                                                 <Row>
                                                     <Minutes>Minutes:999</Minutes>
                                                     <Texts>Texts:99994569</Texts>
                                                     <Data>Data:100</Data>
                                                     <Content>Content:No</Content>
                                                     <Roaming>Roaming:Y + 2000</Roaming>
                                                     <Monthly>Monthly:398</Monthly>
                                                     <Upfront>Upfront:0</Upfront>
                                                 </Row>
                                                 <Row>
                                                     <Minutes>Minutes:99</Minutes>
                                                     <Texts>Texts:92569</Texts>
                                                     <Data>Data:10</Data>
                                                     <Content>Content:No</Content>
                                                     <Roaming>Roaming:Y + 2000</Roaming>
                                                     <Monthly>Monthly:38</Monthly>
                                                     <Upfront>Upfront:0</Upfront>
                                                 </Row>
                                             </SubCategory>
                                         </Tariff>
                                     </Contract>
                                 </Device>
                             </Category>
                         </DPS>

希望它能激发一些想法。再次为VB道歉。我试过转换它