简体   繁体   English

C#如何选择具有匹配值的xml所有节点

[英]C# How to select all nodes of xml that have matching values

Below is an example of my starting xml and the xml result i'm trying to achieve. 以下是我尝试开始的xml和xml结果的示例。 What i'm trying to figure out is not how to create the desired xml but how to grab all matches nodes that have the same starting value. 我要找出的不是如何创建所需的xml,而是如何获取具有相同起始值的所有匹配节点。 For example below, you'll see the xml has apples, there are two nodes with apples. 例如,在下面的示例中,您将看到xml有苹果,有两个带有苹果的节点。 I want to find all those nodes and then create a custom xml afterwards. 我想找到所有这些节点,然后再创建一个自定义xml。

How do you loop for all nodes of an xml and then find all results on that same node level that have matching values? 如何循环查找xml的所有节点,然后在同一节点级别上找到具有匹配值的所有结果?

<?xml version="1.0"?>
<results>
    <result>
        <fruit>apples</fruit>
        <price>0</price>
    </result>
    <result>
        <fruit>pears</fruit>
        <price>1</price>
    </result>
    <result>
        <fruit>apples</fruit>
        <price>2</price>
    </result>
</results>



<?xml version="1.0"?>
<results>
    <result>
        <fruit>apples</fruit>
        <prices>
            <price>0</price>
            <price>2</price>
        </prices>
    </result>
    <result>
        <fruit>pears</fruit>
        <prices>
            <price>1</price>
        </prices>
    </result>
</results>

You can accomplish this by using XDocument . 您可以使用XDocument完成此操作。 Do not forget to import. 不要忘记导入。

 using System.Xml.Linq;
 using System.Xml.XPath;

load document 载入文件

      XDocument doc = XDocument.Load("C:\\t\\My File2.txt");
  1. Select all result elements 选择所有结果元素
  2. Group by fruit value for example 3 apples 1 pears 按水果价值分组,例如3个苹果1个梨
  3. Put the result elements from group and add them into an array 将结果元素从组中放入并添加到数组中
  4. Create list that contains the array with the result elements 创建包含结果元素数组的列表

      List<XElement[]> multipleElements = doc .XPathSelectElements("results/result") .GroupBy(result => result.Element("fruit").Value) .Select(groupContent => groupContent.ToArray()) .ToList(); 

=========== result =================== ===========结果===================

 List [0] { apples,apples} 
 List [1] { pear }

XML I tested on: 我测试过的XML:

 <?xml version="1.0"?> <results> <result> <fruit>apples</fruit> <price>0</price> </result> <result> <fruit>pears</fruit> <price>1</price> </result> <result> <fruit>apples</fruit> <price>2</price> </result> </results> 

This VB code creates the desired output. 此VB代码创建所需的输出。 It selects as results and orders them by fruit value, and then a simple loop to create the desired output. 它选择结果作为结果并按水果值排序,然后进行简单循环以创建所需的输出。

    Dim xe As XElement
    ' to load from a file
    ' Dim yourpath As String = "your path here"
    'xe = XElement.Load(yourpath)

    ' for testing
    xe = <results>
             <result>
                 <fruit>apples</fruit>
                 <price>0</price>
             </result>
             <result>
                 <fruit>pears</fruit>
                 <price>1</price>
             </result>
             <result>
                 <fruit>apples</fruit>
                 <price>2</price>
             </result>
         </results>


    Dim oxe As XElement = <results></results>
    Dim rsltproto As XElement = <result>
                                    <fruit></fruit>
                                    <prices></prices>
                                </result>
    Dim rslt As XElement
    Dim fruit As String
    'select all <result> order by fruit values
    Dim allfruits As IEnumerable(Of XElement) = xe...<result>.OrderBy(Function(el) el.<fruit>.Value)

    'simple loop to create new XML
    For Each el As XElement In allfruits
        If el.<fruit>.Value <> fruit Then
            If rslt IsNot Nothing Then
                oxe.Add(rslt)
            End If
            fruit = el.<fruit>.Value
            rslt = New XElement(rsltproto)
            rslt.<fruit>.Value = fruit
        End If
        rslt.<prices>.LastOrDefault.Add(el.<price>)
    Next
    If rslt IsNot Nothing Then
        oxe.Add(rslt)
    End If


    ' to save file
    ' xe.Save(yourpath)

This is a simple change to Timon's answer above 这是对上面Timon答案的简单更改

var doc = XDocument.Load(@"<path>\test.xml");

var fruitPrices = doc.XPathSelectElements("results/result")
        .Select(d => new { 
            Fruit = d.Element("fruit").Value,
            // TODO: parse to int if required
            Price = d.Element("price").Value
        })
        .GroupBy(f => f.Fruit)
        .Select(g => new {Fruit = g.Key, Prices = g.Select(x => x.Price)})
        .ToList();

In LinqPad this gives 在LinqPad中,这给出了

在此处输入图片说明

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM