Parsing a section of XML - c#

I have a section of XML that I am trying to pull out a name from.
the XML looks like this:
here is the xml layout.
<point href="/software/point/av/371/">
<obj is="testdata/">
<bool val="true" name="eventDetectionEnable" />
<real val="-500.6300048828125" name="minimumValue" />
<int val="0" name="controlClass" />
<int val="1490" name="revision" />
<real val="0" name="highLimit" />
<int val="6" name="dimensionality" />
<reltime val="PT0S" name="heartbeatInterval" />
<enum val="event" name="notifyType" />
<str val="Verticle Spread Pressure" name="name" />
<real val="0" name="deadband" />
<real val="0" name="lowLimit" />
<str val="" name="protocolID" />
<str val="" name="description" />
<reltime val="PT0S" name="eventTimeDelay" />
<real val="1" name="covIncrement" />
<real val="7.9999995231628418" name="relinquishDefault" />
<op name="notifyNow" />
<real val="500.6300048828125" name="maximumValue" />
</obj>
</point>
I need to pull out the name from line
<str val="Verticle Spread Pressure" name="name" />
I can get a list of all the nodes and read the href tag, but nothing below
var data = OpenPLCfile(ofd.FileName, "pointconfig.xml");
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(data);
string xpath = "PointsConfiguration/SoftwarePoints/point";
var nodes = xmlDoc.SelectNodes(xpath);
foreach (XmlNode childrenNode in nodes)
{
string pointID = childrenNode.Attributes["href"].Value;
Console.WriteLine(pointID)
}

You can apply an XPath expression on the XmlNode via the SelectSingleNode method.
XmlNode nameNode = childrenNode.SelectSingleNode("obj/str[#name='name']/#val");
string name = nameNode.Value;
Full example
var data = OpenPLCfile(ofd.FileName, "pointconfig.xml");
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(data);
string xpath = "PointsConfiguration/SoftwarePoints/point";
var nodes = xmlDoc.SelectNodes(xpath);
foreach (XmlNode childrenNode in nodes)
{
string pointID = childrenNode.Attributes["href"].Value;
Console.WriteLine(pointID)
XmlNode nameNode = childrenNode.SelectSingleNode("obj/str[#name='name']/#val");
string name = nameNode.Value;
Console.WriteLine(name);
}

If you only want to get the value of name attribute from the element str where value of val attribute is "Verticle Spread Pressure", then here is the solution:
var data = OpenPLCfile(ofd.FileName, "pointconfig.xml");
XDocument doc = XDocument.Parse(data);
var strElements = doc.Descendants("str");
var targetElement = strElements.Where(x => x.Attribute("val") != null && x.Attribute("val").Value == "Verticle Spread Pressure").FirstOrDefault();
if (targetElement != null)
{
string name = targetElement.Attribute("name").Value;
}
System.Xml.Linq is the namespace for XDocument

Using Xml Linq you can get a dictionary of all named items
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
Dictionary<string, string> dict = doc.Descendants("obj").FirstOrDefault().Elements()
.GroupBy(x => (string)x.Attribute("name"), y => (string)y.Attribute("val"))
.ToDictionary(x => x.Key, y => y.FirstOrDefault());
}
}
}

Related

How to get the value of an attribute from a complex XML document in C# UWP?

XML file:
<?xml version="1.0"?>
<DATA>
<Element Name="Visualisie:ST_Visu_FilterdatenNeutral" Type="PvParameter">
<Group ID="Visualisie:ST_Visu_FilterdatenNeutral">
<Property ID="S_Kunde_Firma" DataType="STRING" Value="Biotest AG" />
<Property ID="S_Gebaeude" DataType="STRING" Value="A" />
<Property ID="S_Raum" DataType="STRING" Value="A003" />
<Property ID="S_Anlage" DataType="STRING" Value="A003 Spuelbereich" />
<Property ID="S_Filter_ID" DataType="STRING" Value="1046362" />
<Property ID="S_Reinraumklasse" DataType="STRING" Value="GMP D" />
</Group>
</Element>
</DATA>
I tried it coding like down below but it wont work:
public async Task getdata()
{
StorageFile file = await StorageFile.GetFileFromPathAsync(PathforNeutralFilterDatei);
IRandomAccessStreamWithContentType stream = await file.OpenReadAsync();
StreamReader rdr = new StreamReader(stream.AsStream(), Encoding.GetEncoding("ISO-8859-1"));
var contents = rdr.ReadToEnd();
XDocument doc = XDocument.Parse(contents);
IEnumerable<string> skundename = from SKF in doc.Descendants("Property").
Where(v => v.Attribute("ID").Value == "S_Kunde_Firma")
select SKF.Attribute("Value").Value;
foreach (XElement SKF in skundename)
{
string temp = SKF.Descendants("Property").Where(v => v.Attribute("ID").Value == "S_Kunde_Firma").ToString();
}
}
I just want to get the value from the attribute 'Value' which is "Biotest AG" and save this string value in a public defined string (temp).
I like using dictionaries :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.IO;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
Dictionary<string, string> dict = doc.Descendants("Property")
.GroupBy(x => (string)x.Attribute("ID"), y => (string)y.Attribute("Value"))
.ToDictionary(x => x.Key, y => y.FirstOrDefault());
}
}
}
how to get the value of an attribute from a complex XML document in C# UWP?
I checked your code, and the linq is correct, but the for-each segment is incorrect. Because the type of skundename is IEnumerable<string>. Please check the following code.
IEnumerable<string> skundename = from SKF in doc.Descendants("Property").
Where(v => v.Attribute("ID").Value == "S_Kunde_Firma")
select SKF.Attribute("Value").Value;
foreach (string item in skundename)
{
string temp = item;
}

C#: Get XML node content with all parent tags

There is a XML file:
<favorites>
<movies>
<movie title="The Godfather" year="1974" />
<movie title="The Terminator" year="1984" />
<movie title="Dark Knight" year="2008" />
</movies>
<books>
<book title = "1984" author="George Orwell" />
<book title = "Robinson Crusoe"" author="Daniel Defoe"/>
<book title = "Frankenstein" author="Mary Shelly" />
</books>
<music>
<artist title = "Beatles" genre="rock" />
<artist title = "Queen" genre="rock" />
<artist title = "Metallica" rock="heavy metal" />
</music>
</favorites>
I need to filter a specific node (music) with all parent & child nodes.
The result should be:
<favorites>
<music>
<artist title="Beatles" genre="rock" />
<artist title="Queen" genre="rock" />
<artist title="Metallica" rock="heavy metal" />
</music>
</favorites>
I've found a solution to filter XML using System.XML & LINQ:
XDocument xdoc = XDocument.Parse(xmlString);
xdoc.Descendants()
.Where(x => x.Name != "favorites" & x.Name != "music" & x.Name != "artist")
.Remove();
Console.WriteLine(xdoc.ToString());
The working sample is here: https://dotnetfiddle.net/NnA4h7#
The problem is that I have to specify all parent & child nodes in my query.
Is there a way to get the same result with specifying a wanted node only (movies, books, music) ?
Here is another method that is a little simpler :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
XElement favorites = doc.Descendants("favorites").FirstOrDefault();
favorites.ReplaceNodes(favorites.Element("music")));
}
}
}
Basically you need to remove all nodes except for the parents of music, music itself and its descendants.
var music = xdoc.Descendants().Where(x => x.Name == "music");
xdoc.Descendants().Where(x =>
!music.AncestorsAndSelf().Contains(x)
&& !music.Descendants().Contains(x)
).Remove();
Console.WriteLine(xdoc.ToString());
It returns:
<favorites>
<music>
<artist title="Beatles" genre="rock" />
<artist title="Queen" genre="rock" />
<artist title="Metallica" rock="heavy metal" />
</music>
</favorites>
UPDATE: supporting multiple nested levels between favorites and music. Optimized for running with big files:
XDocument xdoc = XDocument.Parse(xmlString);
var music = xdoc.Descendants().Where(x => x.Name == "music");
var parents = music.Ancestors().Reverse()
.Select(a=>new XElement(a.Name.LocalName)).ToArray();
XElement root = new XElement(xdoc.Root.Name.LocalName);
XDocument xdoc2 = new XDocument(root);
XElement lastAdded = root;
for (int i = 1; i < parents.Count(); i++)
{
lastAdded.Add(parents[i]);
lastAdded = parents[i];
}
lastAdded.Add(music);
Console.WriteLine(xdoc2.ToString());

Selecting certain values within a string

I have a string in which I need to extract all of the FieldRef names from the ViewField section of the string. They need to be input into an array. Been struggling with this for a while since im new to c#. Thanks.
<View>
<Query>
<OrderBy>
<FieldRef Name="ID" />
</OrderBy>
</Query>
<ViewFields>
<FieldRef Name="LinkTitle" />
<FieldRef Name="User" />
<FieldRef Name="Permissions" />
</ViewFields>
<RowLimit Paged="TRUE">30</RowLimit>
<JSLink>clienttemplates.js</JSLink>
<XslLink Default="TRUE">main.xsl</XslLink>
<Toolbar Type="Standard"/>
</View>
This returns only FieldRefs from ViewFields:
var doc = XDocument.Parse(xmlString);
var results = doc.Root.Element("ViewFields").Elements("FieldRef")
.Select(e => e.Attribute("Name").Value);
You can use XDocument to load the string as xml and then use Linq to get the values.
var doc = XDocument.Parse(str);
var res = doc
.Descendants("ViewFields")
.Descendants("FieldRef")
.Select(x => x.Attribute("Name").Value);
Load method is trying to load xml from a file and LoadXml from a string
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(xml);
string xpath = "View/Query/ViewFields";
var nodes = xmlDoc.SelectNodes(xpath);
foreach (XmlNode childrenNode in nodes)
{
var arr = childrenNode.SelectSingleNode("//FieldRef").Value;
}

How to Get Element Names from XElement Using C#?

I have a Xml and i have to get the element name
<Data>
<Test key="G" modifier="control" />
<Test1 key="E" modifier="control" />
<Test3 />
<Test4 />
</Data>
XDocument xd = XDocument.Load("..\\Cmd.xml");
IEnumerable<XElement> xeCmdData = Cmd.XPathSelectElements(".//Data");
foreach (XElement xeData in xeCmdData)
{
// here i am getting the whole xml how to get Element name ...
// Like <Data>
// <Test key="G" modifier="control" />
// <Test1 key="E" modifier="control" />
// <Test3 />
// <Test4 />
// </Data>
}
How to get Element names ?
XDocument xd = XDocument.Load("..\\Cmd.xml");
IEnumerable<string> names = xd.XPathSelectElements("//Data/*")
.Select(e => e.Name.LocalName);
Or without XPath
IEnumerable<string> names = xd.Descendants("Data")
.Elements()
.Select(e => e.Name.LocalName);
Result:
Test
Test1
Test3
Test4

XDocument get all nodes with attributes

I have the following XML document:
<parameters>
<source value="mysource" />
<name value="myname" />
<id value="myid" />
</parameters>
I'm trying to parse this XML, using XDocument so that I would get a list (Dictionary) containing the node and it's value:
source => mysource,
name => myname,
id => myid
Any ideas on how I can do this?
I tried this out in LINQPad and it provides what you are looking for:
string xml = #"<parameters>
<source value=""mysource"" />
<name value=""myname"" />
<id value=""myid"" />
</parameters>";
var doc = XDocument.Parse(xml);
IDictionary dict = doc.Element("parameters")
.Elements()
.ToDictionary(
d => d.Name.LocalName, // avoids getting an IDictionary<XName,string>
l => l.Attribute("value").Value);
Provided you have a document with the content you show here, this should work:
XDocument doc = ...;
var dict = doc.Root
.Elements()
.ToDictionary(
e => e.Name.ToString(),
e => e.Attribute("value").Value);
XDocument x = XDocument.Parse(
#"<parameters>
<source value=""mysource"" />
<name value=""myname"" />
<id value=""myid"" />
</parameters>");
var nodes = from elem in x.Element("parameters").Elements()
select new { key = elem.Name.LocalName, value = elem.Attribute("value").Value };
var list = new Dictionary<string, string>();
foreach(var node in nodes)
{
list.Add(node.key, node.value);
}
You can use xmldocument/ xmtextreader object use these links these will help
http://msdn.microsoft.com/en-us/library/c445ae5y(v=vs.80).aspx
http://www.c-sharpcorner.com/uploadfile/mahesh/readwritexmltutmellli2111282005041517am/readwritexmltutmellli21.aspx
but i strongly suggest if possible use linq to xml that is far easy and manageable
http://www.codeproject.com/KB/linq/LINQtoXML.aspx
Something like this
XDocument doc = XDocument.Parse(xmlText);
IDictionary<string,string> dic = doc.Elements("parameters").ToDictionary(e => e.Name.LocalName, e => e.Value);
Hope this helps
using System;
using System.Linq;
using System.Xml.Linq;
using System.Collections.Generic;
class Program{
static void Main(){
var doc = XDocument.Load("1.xml");
var result = (from node in doc.Root.Elements()
select new{ Key = node.Name, Value = node.Attribute("value").Value})
.ToDictionary(p =>p.Key, p=>p.Value);
foreach(var p in result) Console.WriteLine("{0}=>{1}", p.Key, p.Value);
}
}

Categories

Resources