Below is an example of my starting xml and the xml result i'm trying to achieve. 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. For example below, you'll see the xml has apples, there are two nodes with apples. I want to find all those nodes and then create a custom xml afterwards.
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 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 . Do not forget to import.
using System.Xml.Linq;
using System.Xml.XPath;
load document
XDocument doc = XDocument.Load("C:\\t\\My File2.txt");
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 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. 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
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
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.