Reputation: 7348
I have a plist file from an iPhone app. It looks like this below:
<plist version="1.0">
<dict>
<key>barcodes</key>
<array>
<string>JF893J89FJ-66666</string>
<string>JF893J89FJ-55555</string>
</array>
<key>currentStep</key>
<integer>1</integer>
<key>dateFinished</key>
<date>2010-05-10T18:33:25Z</date>
<key>dateStarted</key>
<date>2010-05-10T18:33:25Z</date>
<key>description</key>
<string>TEST</string>
<key>geoRequired</key>
<string>N</string>
<key>inProgress</key>
<string>N</string>
<key>jobID</key>
<integer>10085</integer>
<key>jobSteps</key>
<array>
<dict>
<key>label</key>
<string>TEST</string>
<key>response</key>
<string>matt hudson</string>
<key>stepID</key>
<integer>1103</integer>
<key>typeID</key>
<integer>4</integer>
</dict>
</array>
</dict>
</plist>
I need to get the array after jobSteps.
I have this so far:
XDocument xml = XDocument.Load(rri.Response);
var q = from elements in xml.Descendants("plist").Descendants("dict")
where elements.Value == "jobSteps"
select elements;
But I need to get the next item after the element that has jobSteps in it.
Upvotes: 14
Views: 13322
Reputation: 3419
var q = xml
.Descendants("plist")
.Descendants("dict")
.Where(item => item.Value == "jobSteps")
.Select(item => item.NextNode)
.SingleOrDefault() // add this if you expect single match
;
The q
will be either a single array node or a sequence of array nodes depending whether you use SingleOrDefault()
.
Upvotes: 2
Reputation: 83358
EDIT
I believe this will get you the element after the jobSteps node:
XElement elementAfterJobsteps = xml.Descendants("plist").FirstOrDefault().Descendants("jobSteps").FirstOrDefault().ElementsAfterSelf().FirstOrDefault();
END EDIT
foreach (XElement El in xml.Descendants("plist")) {
var localResults =
from elements in El.Descendants("dict")
where elements.Value == "jobSteps"
select elements;
//process localResults
}
Or, even simpler, try method syntax
foreach (XElement El in xml.Descendants("plist")) {
var localResults = El.Descendants("dict").Where(dict => dict.Value == "jobSteps");
//process localResults
}
Upvotes: 5
Reputation: 30830
var q = (from key in xml.Descendants("key")
where key.Value == "jobSteps"
from array in xml.Descendants("array")
select key.NodesAfterSelf() // In all nodes after <key>jobSteps</key>
.OfType<XElement>() // which are elements
.Where(element => element.Name == "array") // and name is array,
.First() // select first of them
).First(); // and select first of whatever is found
NOTE: Above code may throw InvalidOperationException
while calling First()
if no result is found.
Upvotes: 1
Reputation: 1500485
It's not entirely clear to me whether Adam's solution is what you want, but if not, you might want to look at the NextNode property:
Gets the next sibling node of this node.
For instance, this prints the array element:
using System;
using System.Linq;
using System.Xml.Linq;
class Test
{
static void Main()
{
XDocument doc = XDocument.Load("test.xml");
foreach (var element in doc.Descendants("key")
.Where(x => (string) x == "jobSteps"))
{
Console.WriteLine(element.NextNode);
}
}
}
Note that it's skipping the whitespace between elements - but if there were any text between that and the array, it wouldn't work - so you'd want:
Console.WriteLine(element.NodesAfterSelf().OfType<XElement>().First());
Upvotes: 18