How do I get XML path by its value? - c#

I need to get the xml path opf the xml file by providing the value of an xml child element as the input.
For example:
XML file:
<?xml version="1.0"?>
<document-inquiry xmlns="http://ops.epo.org">
<publication-reference data-format="docdb" xmlns="http://www.epo.org/exchange">
<document-id>
<country>EP</country>
<doc-number>1000</doc-number>
<kind>A1</kind>
</document-id>
</publication-reference>
</document-inquiry>
For the above XML file. I need to get the XML path by using the value "1000".
If my input is value of the element "1000"
Output i need is :
<document-id>
<country>EP</country>
<doc-number>1000</doc-number>
<kind>A1</kind>
</document-id>
I need to achieve this using c# code. Can anyone please help me out on this...

You could use XPathSelectElement extension method:
using System;
using System.Xml;
using System.Xml.Linq;
using System.Xml.XPath;
class Program
{
static void Main()
{
var doc = XDocument.Load("test.xml");
var ns = new XmlNamespaceManager(new NameTable());
ns.AddNamespace("ns", "http://www.epo.org/exchange");
var elem = XDocument.Load("test.xml")
.XPathSelectElement("//ns:document-id[ns:doc-number='1000']", ns);
if (elem != null)
{
Console.WriteLine(elem.ToString());
}
}
}
You could use XPathSelectElements if you want to select multiple nodes that correspond to this criteria.

You can select the element that you want with a linq query.
var number = "1000";
var xml = XDocument.Parse( xml_string );
XNamespace ns = "http://www.epo.org/exchange";
var result = (from data in xml.Descendants(ns + "document-id")
where data.Element(ns + "doc-number").Value == number
select data).FirstOrDefault();
.FirstOrDefault() returns the first matching element or null. You could instead use .List() to get a list containing all matching elements.

Related

How to filter data from xml using xmldocument class & xpath

I have xml stored in string variable. from that xml I need to filter data based on StandardValue. I want to extract only those records whose StandardValue is not null & not empty. I tried but my code did not work.
string xmldoc= #"<?xml version=""1.0"" encoding=""utf-8""?>
<TickerBrokerStandardDateLineitem>
<Ticker />
<TickerID />
<TickerBrokerStandardDateLineitemValues>
<TickerBrokerStandardDateLineitemValue>
<TabName>Consensus Model</TabName>
<StandardDate>1Q 2010</StandardDate>
<BRTab>Income Statement</BRTab>
<BRLineItem>NET REVENUES</BRLineItem>
<Action>Extracted</Action>
<StandardLineItem>Net Revenue</StandardLineItem>
<StandardValue>329.623</StandardValue>
</TickerBrokerStandardDateLineitemValue>
<TickerBrokerStandardDateLineitemValue>
<TabName>Consensus Model</TabName>
<StandardDate>2Q 2010</StandardDate>
<BRTab>Income Statement</BRTab>
<BRLineItem>NET REVENUES</BRLineItem>
<Action>Extracted</Action>
<StandardLineItem>Net Revenue</StandardLineItem>
<StandardValue></StandardValue>
</TickerBrokerStandardDateLineitemValue>
<TickerBrokerStandardDateLineitemValue>
<TabName>Consensus Model</TabName>
<StandardDate>2Q 2010</StandardDate>
<BRTab>Income Statement</BRTab>
<BRLineItem>NET REVENUES</BRLineItem>
<Action>Extracted</Action>
<StandardLineItem>Net Revenue</StandardLineItem>
<StandardValue/>
</TickerBrokerStandardDateLineitemValue>
</TickerBrokerStandardDateLineitemValues>
</TickerBrokerStandardDateLineitem>";
XmlDocument doc = new XmlDocument();
doc.LoadXml(xmldoc);
XmlNodeList nodeList = doc.GetElementsByTagName("TickerBrokerStandardDateLineitemValue");
List<string> list = new List<string>();
foreach (XmlNode item in nodeList)
{
foreach (XmlElement i in item)
{
if (i.Name == "StandardValue")
{
if (i.InnerText == string.Empty)
{
list.Add(item.OuterXml);
}
}
}
}
string a = string.Empty;
foreach (var item in list)
{
a = doc.InnerXml.Replace(item, "");
}
string str1 = doc.OuterXml;
My above code does not work. basically how to filter with xpath that return only those records whose StandardValue is not null & not empty.
How to achieve it with XmlDocument class instead of xdocument.
At end I have to stored filtered record's xml into string. I know XmlDocument class has outer xml property which return full xml.
Give me sample code which will return filter records & stored filter records xml into string.
Use xml linq which is the newer version of the Net xml library :
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)
{
string xml = File.ReadAllText(FILENAME);
XDocument doc = XDocument.Parse(xml);
List<XElement> tickerBrokerStandardDateLineitemValues = doc.Descendants("TickerBrokerStandardDateLineitemValue")
.Where(x => (x.Element("StandardValue") != null) && ((string)x.Element("StandardValue") != string.Empty))
.ToList();
}
}
}
Assuming the input string your provided in the question.
This will select all TickerBrokerStandardDateLineitemValue values that has StandardValue element and it's not empty or white space (normalize-space).
normalize-space:
strips leading and trailing white-space from a string, replaces
sequences of whitespace characters by a single space, and returns the
resulting string.
var xmlDoc = new XmlDocument();
xmlDoc.LoadXml(xmlStr); // <input from the question>
var nodes = xmlDoc.SelectNodes("//TickerBrokerStandardDateLineitemValue[StandardValue and string-length(normalize-space(StandardValue))]");

Retrieving an Attribute Value from an XNode

I have my XML file loaded and then I select my last element. Here is the code:
XDocument doc = XDocument.Load("something.xml");
var last = doc.Root.LastNode;
The code above outputs the last element on the XML file. Here is the code:
<link num="4" url="yahoo.com">Yahoo</link>
I want to be able to select the value 4 of num. Here is the code:
num="4"
How can I select the number 4 from my last node?
Try this:
XDocument xDoc = XDocument.Parse(xml);
string num = xDoc.Root.Elements().Last().Attribute("num").Value;
Console.WriteLine(num);
Make sure you have added the following using:
using System.Linq;
using System.Xml.Linq;
You can get value with following code.
var numValue = ((XElement)last).Attributes("num").FirstOrDefault().Value

Get a xml element with specific attribute value in c#

I need to get a value of a SubTopic element which has an attribute called "Name" with specific value. I do it this way;
IEnumerable<XElement> list =
(from el in xdoc.Elements()
where (string)el.Attribute("Name") == "creatingTests"
select el);
The collection has zero elements.
I tried putting xdoc.Elements("SubTopic") instead of empty parameter, but with no success.
My XML file structure;
<?xml version="1.0" encoding="windows-1250" ?>
<Help Title="TestTool - tematy pomocy">
<Topic Name="creatingTests" Title="Tworzenie testów">
<SubTopic Name="saveload" Title="Zapis i odczyt z pliku">
Content
</SubTopic>
</Topic>
</Help>
How can I get that value of Help/Topic(Name="creatingTests")?
xdoc is of course XDocument object with loaded xml and it does have the content of my file.
xdoc.Elements() returns only one element - the Root of XML tree (it's <Help> element in your example.
Change your query to:
IEnumerable<XElement> list =
(from el in xdoc.Root.Elements()
where (string)el.Attribute("Name") == "creatingTests"
select el);
It returns collection with one element. Use First or FirstOrDefault to get it as single item, not a collection:
XElement item = (from el in xdoc.Root.Elements()
where (string)el.Attribute("Name") == "creatingTests"
select el).FirstOrDefault();
Here's an alternative by using System.Xml.XPath:
using System.Xml.Linq;
using System.Xml.XPath;
class Program
{
static void Main(string[] args)
{
var xdoc = XDocument.Load("input.xml");
var subTopic = xdoc
.XPathSelectElement("//Topic[#Name='creatingTests']/SubTopic");
}
}
Very easy and simplest way is to use XSLT..
1.Create an XSLT Template.
2.Call it in c#.
xmlDaynamic.DocumentContent = "Your XML Input";
xmlDaynamic.TransformSource = "YourTemplate with extension";
3.Your task is done.
4.xmlDaynamic is a server control.
Try using XPATH
http://support.microsoft.com/kb/308333
"//Topic[#Name='creatingTests']"

Parsing complex XML with C#

I am trying to parse a complex XML with C#, I am using Linq to do it. Basically, I am doing a request to a server and I get XML, this is the code:
XElement xdoc = XElement.Parse(e.Result);
this.newsList.ItemsSource =
from item in xdoc.Descendants("item")
select new ArticlesItem
{
//Image = item.Element("image").Element("url").Value,
Title = item.Element("title").Value,
Description = this.Strip(item.Element("description").Value).Substring(0, 200).ToString()
}
And this is the XML structure:
<item>
<test:link_id>1282570</test:link_id>
<test:user>SLAYERTANIC</test:user>
<title>aaa</title>
<description>aaa</description>
</item>
How I can access to the property test:link_id for example?
Thanks!
Currently your XML is invalid since the test namespace is not declared, you can declare it like this:
<item xmlns:test="http://foo.bar">
<test:link_id>1282570</test:link_id>
<test:user>SLAYERTANIC</test:user>
<title>aaa</title>
<description>aaa</description>
</item>
Having this you can use XNamespace to qualify the XML element you want with the correct namespace:
XElement xdoc = XElement.Parse(e.Result);
XNamespace test = "http://foo.bar";
this.newsList.ItemsSource = from item in xdoc.Descendants("item")
select new ArticlesItem
{
LinkID = item.Element(test + "link_id").Value,
Title = item.Element("title").Value,
Description = this.Strip(item.Element("description").Value).Substring(0, 200).ToString()
}
To write a query on XML that is in a
namespace, you must use XName objects
that have the correct namespace. For
C#, the most common approach is to
initialize an XNamespace using a
string that contains the URI, then use
the addition operator overload to
combine the namespace with the local
name.
To retrieve the value of the link_id element you will need to declare and use an XML namespace for the test:link element.
Since you did not show the namespace declaration in your example XML, I am going to assume it is declared somewhere elese in the XML document. You need to locate the namespace declaration in the XML ( something like xmlns:test="http://schema.example.org" ) which is often declared in the root of the XML document.
After you know this, you can do the following to retrieve the value of the link_id element:
XElement xdoc = XElement.Parse(e.Result);
XNamespace testNamespace = "http://schema.example.org";
this.newsList.ItemsSource = from item in xdoc.Descendants("item")
select new ArticlesItem
{
Title = item.Element("title").Value,
Link = item.Element(testNamespace + "link_id").Value,
Description = this.Strip(item.Element("description").Value).Substring(0, 200).ToString()
}
See the XNamespace and Namespaces in C#, and How to: Write Queries on XML in Namespaces for further information.

How to query a peer XMLNode .NET

I have an xml file. I want to query a peer node in C#.
For ex: For a given input xml file as below,
i want to query the title using the artist as an input. How do i do this ??
i.e Input --> Pink Floyd, Output -----> Division Bell ..
<catalog>
<cd>
<title>Division Bell<title>
<artist>Pink Floyd<artist>
<price>29$<price>
</cd>
<cd>
<title>Relapse<title>
<artist>Eminem<artist>
<price>19$<price>
</cd>
</catalog>
You could use a XDocument:
using System;
using System.Linq;
using System.Xml.Linq;
class Program
{
static void Main()
{
var doc = XDocument.Load("test.xml");
var result =
(from cd in doc.Root.Descendants("cd")
let artist = cd.Element("artist")
let title = cd.Element("title")
where artist != null && title != null && artist.Value == "Pink Floyd"
select title.Value
).FirstOrDefault();
Console.WriteLine(result);
}
}
Its quite easy tor read xml in .net
XDocument loaded = XDocument.Load(#"C:\youxml.xml");
var query = from xElem in loaded.Descendants("cd")
where xElem.Element("artist").Value == "Eminem"
select new Friend
{
Title = xElem.Attribute("title").Value
};
Make use of Linq To XML or XLINQ will resolve you issue easily.
Also check this : http://msdn.microsoft.com/en-us/library/bb308960.aspx
You can also use XPath syntax.
here is an example:
string inputArtist = "Pink Floyd";
var doc = XDocument.Load("test.xml");
XmlNode cdTitleNode = doc.SelectSingleNode("//cd[artist='" + inputArtist + "']/title");
string outputTitle = cdTitleNode.InnerText;
There is an excellent XPATH simulator on http://www.whitebeam.org/library/guide/TechNotes/xpathtestbed.rhtm to try you Xpath expressions.
You can also found a good tutorial there, but a fast search on the web will result in many web pages explaining all about XPath usage and syntax.
Using XPath, you can return a match:
using System.Xml;
using System.Xml.XPath;
public string QuerySearch(string file, string artist) {
// create an XML Document and load the file
XmlDocument xd = new XmlDocument();
xd.Load(file);
// get the root xml element
XmlElement root = xd.DocumentElement;
// get the list of artists
XmlNodeList aristList = root.GetElementsByTagName("artist");
// get the list of titles's
XmlNodeList titleList = root.GetElementsByTagName("title");
// find match
for (int i = 0;i < aristList.Count; i++) {
if (aristList.Item(i).InnerText == artist) {
return titleList.Item(i).InnerText
}
}
return "no match found.";
}

Categories