如何使用c#在xml文件中的子节点下读取多个具有相同名称的标签?

时间:2016-11-04 05:43:21

标签: c# xml linq

对于下面的xml我想读取所有行节点的值,因为你可以看到子类别标签下有多个行标签,所以对于特定的子类别(假设SubCategory ID =" Standard")我想要获取所有行标记?如何使用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>

2 个答案:

答案 0 :(得分:1)

首先,将XML加载到XDocument中。

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

然后,您可以查询ID为“Standard”的所有SubCategory元素,最后询问其所有子元素行。

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

编辑:要从上面的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关键字后面正在选择行。

编辑2 :将每个元素中的额外位文本确认为“输入错误”,您可以完全跳过内联函数并简化rowData select to this:

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
});

答案 1 :(得分:0)

使用我有权访问的转换器无法将此VB代码转换为C#。我知道XML文字在C#中没有对应物,但除了要有一些测试数据之外什么都不需要。

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

让我们通过查看标准中的每一行开始。添加了调试以帮助可视化。

    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。我确实试图转换它。