Most elegant way to query XML string using XPath - c#

I'm wondering what the most elegant way is in C# to query a STRING that is valid xml using XPath?
Currently, I am doing this (using LINQ):
var el = XElement.Parse(xmlString);
var h2 = el.XPathSelectElement("//h2");

Simple example using Linq to XML :
XDocument doc = XDocument.Parse(someStringContainingXml);
var cats = from node in doc.Descendants("Animal")
where node.Attribute("Species").Value == "Cat"
select node.Attribute("Name").Value;
Much clearer than XPath IMHO...

Just for the record, I did not want to go with Linq2XML but XPath and found this way:
var xPathDoc = new XPathDocument(new StringReader("your XML string goes here"));

Related

XmlElement convert open tag to string c#

I need to convert to string a subset of OuterXml content of a XmlElement as in the following example.
Imagine I have an XmlElement object representing the some-element tag
<some-element attribute="value">
<inner-element>
text content
</inner-element>
</some-element>
What's the best approach to get a string that is just <some-element attribute="value">?
If possible, I'd prefer a solution without regular expressions involved, but using DOM classes
You can get the full XML of the element(which includes the close tag) by shallow cloning the node and then grabbing the outer XML of the node:
var xml = #"<some-element attribute=""value"">
<inner-element>
text content
</inner-element>
</some-element>";
XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);
MessageBox.Show(doc.DocumentElement.CloneNode(false).OuterXml);
I think after that point you will have to do some string manipulation to get exactly what you want, but that is relatively easy:
var outer = doc.DocumentElement.CloneNode(false).OuterXml;
var final = outer.Substring(0, outer.LastIndexOf(">", outer.Length - 2)+1);
MessageBox.Show(final);
I finally solved it by creating a temporary XElement instead using LINQ
IEnumerable<XAttribute> attributes = (from XmlAttribute xmlAttribute in node.Attributes select new XAttribute(xmlAttribute.Name, xmlAttribute.Value));
var xElement = new XElement(node.Name, attributes);
return xElement.ToString();

Using linq to xml with Htmlagilitypack

I am using HtmlAgilityPack for creatin a htmldocument from the string, like:
HtmlDocument updoc = new HtmlDocument();
updoc.load(stringContents);
Now i want to insert the HtmlNodes as a child of XElement. I tried :
XDocument xdoc = XDocument.load(path);
XElement body = xdoc.Descendants(ns + "body").Single();
body.Add(updoc.GetElementbyId("h"));
body.Add(updoc.GetElementbyId("m"));
body.Add(updoc.GetElementbyId("f"));
but result will only the object names (HtmlNodeAgilityPack, ..), not works. Basically i am trying to using the combination of HtmlAgilityPack with linq to xml. Is this possible ?
I'm just googling around for stuff, so this may not work for you. But you need to use the properties of the HtmlNode returned by GetElementbyId() to create your element.
So something like this:
HtmlNode node = updoc.GetElementbyId("h");
XElement e;
body.Add(e = new XElement(node.Name, XElement.Parse(node.InnerHtml)));
If the node has HtmlAttribute(s), add them like:
foreach(HtmlAttribute att in node.Attributes)
{
e.Add(new XAttribute(att.Name, att.Value));
}
Why not just use a StringBuilder to generate your xml and parse it with XDocument.Parse(string)
Example :
StringBuilder xmlBuilder = new StringBuilder();
//Build xml with the builder
XDocument xDoc = XDocument.Parse(xmlBuilder.ToString());

what's wrong in this LINQ query

I have the following XML
<School Version="30">
<Math>
<Lesson1 Type="Active">Introduction</Reset_mode>
<Lesson2 Type="Active">Fundamentals</Reset_mode>
</Math>
</School>
I want to get the subelements lesson1, lesson2
I load the XML in XDocument
I have to question - what's wrong in this query
var nodes = from C in document.Element("School").Elements()
where document.Element("School").Elements().Contains(t => t.Name == "Math")
select C ; //shortcutsXMLDocument.SelectNodes(Query);
and it raise and error.
Also can I use XPath with XDocument?
You are looking for a ShortcutList element :
Element("ShortcutList")
Which does not exists.
You should write this to get subLessons :
var items = document.Element("School").Element("Math").Elements();
foreach(var item in items)
{
DoSomething(item);
}
LINQ to XML:
from subject in XDocument.Load(xml).Element("School").Elemens()
where subject.Name == "Math"
select subject.Elements();
XPath using XmlDocument:
var doc = new XmlDocument();
doc.LoadXml(xml);
var nodes = doc.SelectNodes("School/Math/Lesson1 or School/Math/Lesson2");
document.Decendants("Math");
yields you a IEnumrable with your two elements.
it's equal to the xpath //Math
Xpath case used on XElement/XDocument from this namespace System.Xml.XPath.
here is your query for path...
var nodes = from C in document.XPathSelectElements("./Math")
select C; //shortcutsXMLDocument.SelectNodes(Query);

Convert the following Linq to xml to .net 2.0

I am recently working on a .net 2.0 project I have to read some xml files and replace certain elements value.
Wondering how you do it the following not using linq to xml?
IEnumerable<XElement> cities= xmldoc.Descendants("City")
.Where(x => x.Value == "London");
foreach (XElement myElem in cities)
{
myElem.ReplaceWith(new XElement("City", "NewCity"));
}
or
var xElement = xdoc.Descendants("FirstName").Where(x => x.Value == "Max").First();
xElement.ReplaceWith(new XElement("FirstName", "NewValue");
Any suggestions
You can consider using XmlDocument, like this:
string xmlFile = "<xml><data<test /><test /><test /><test /></data></xml>";
var xmlDoc = new XmlDocument();
xmlDoc.Load(xmlFile);
var oNodes = xmlDoc.SelectNodes("//test");
foreach (var oNode in oNodes)
{
oNode.InnerText = "bla bla";
}
xmlDoc.Save("..path to xml file");
(In your case you can use InnerXml property of the document)
http://msdn.microsoft.com/en-us/library/system.xml.xmldocument.aspx
To selectNodes you should pass XPath Query, reference can be found:
http://www.w3schools.com/xpath/
Also if you XML contains namespace, you need to use XmlNamespaceManager:
http://msdn.microsoft.com/en-us/library/system.xml.xmlnamespacemanager.aspx
Otherwise xpath won't work.
You will need to use XmlDocument and query it using XPath with SelectNodes.
It will not be as nice and succint.

Get content of XML node using c#

simple question but I've been dinking around with it for an hour and it's really starting to frustrate me. I have XML that looks like this:
<TimelineInfo>
<PreTrialEd>Not Started</PreTrialEd>
<Ambassador>Problem</Ambassador>
<PsychEval>Completed</PsychEval>
</TimelineInfo>
And all I want to do is use C# to get the string stored between <Ambassador> and </Ambassador>.
So far I have:
XmlDocument doc = new XmlDocument();
doc.Load("C:\\test.xml");
XmlNode x = doc.SelectSingleNode("/TimelineInfo/Ambassador");
which selects the note just fine, now how in the world do I get the content in there?
May I suggest having a look at LINQ-to-XML (System.Xml.Linq)?
var doc = XDocument.Load("C:\\test.xml");
string result = (string)doc.Root.Element("Ambassador");
LINQ-to-XML is much more friendly than the Xml* classes (System.Xml).
Otherwise you should be able to get the value of the element by retrieving the InnerText property.
string result = x.InnerText;
The InnerText property should work fine for you.
http://msdn.microsoft.com/en-us/library/system.xml.xmlnode.innertext.aspx
FWIW, you might consider switching API to linq-to-xml (XElement and friends) as IMHO it's a friendly, easier API to interact with.
System.Xml version (NOTE: no casting to XmlElement needed)
var xml = #"<TimelineInfo>
<PreTrialEd>Not Started</PreTrialEd>
<Ambassador>Problem</Ambassador>
<PsychEval>Completed</PsychEval>
</TimelineInfo>";
XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);
var node = doc.SelectSingleNode("/TimelineInfo/Ambassador");
Console.WriteLine(node.InnerText);
linq-to-xml version:
var xml = #"<TimelineInfo>
<PreTrialEd>Not Started</PreTrialEd>
<Ambassador>Problem</Ambassador>
<PsychEval>Completed</PsychEval>
</TimelineInfo>";
var root = XElement.Parse(xml);
string ambassador = (string)root.Element("Ambassador");
Console.WriteLine(ambassador);
XmlDocument doc = new XmlDocument();
doc.Load("C:\\test.xml");
XmlNode x = doc.SelectSingleNode("/TimelineInfo/Ambassador");
x.InnerText will return the contents
Try using Linq to XML - it provides a very easy way to query xml datasources - http://msdn.microsoft.com/en-us/library/bb387098%28v=VS.100%29.aspx

Categories