Xml Path how to read property name - c#

i need some help. i've got xml like this:
<?xml version='1.0' encoding='utf-8'?>
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
<session-factory>
<property name="connection.provider">NHibernate.Connection.DriverConnectionProvider</property>
<property name="connection.driver_class">NHibernate.Driver.SqlClientDriver</property>
</session-factory>
</hibernate-configuration>
and i want to read property NAME and value (value is between
i have done something like this
XPathNodeIterator iterator = nav.Select("/nh:hibernate-configuration/nh:session-factory/nh:property/#name", manager);
XPathNodeIterator iterator2 = nav.Select("/nh:hibernate-configuration/nh:session-factory/nh:property", manager);
while (iterator.MoveNext() && iterator2.MoveNext())
{
var name = iterator.Current.Value;
var property = iterator2.Current.Value;
}
but it is possible to have only one iterator in that case which i could use to get name and property ?

You can use only the 2nd iterator and use GetAttribute() to read name attribute value :
XPathNodeIterator iterator2 = nav.Select("/nh:hibernate-configuration/nh:session-factory/nh:property", manager);
while (iterator2.MoveNext())
{
var navigator = iterator.Current;
var name = navigator.GetAttribute("name","");
var property = navigator.Value;
}
Anyway, the entire task can be much simpler using XmlDocument, or using LINQ-to-XML as demonstrated below :
var doc = XDocument.Load("path_to_your_xml.xml");
XNamespace d = "urn:nhibernate-configuration-2.2";
foreach(var prop in doc.Descendants(d+"property")
{
var name = (string)prop.Attribute("name");
var property = (string)prop;
}

Related

Get XElement with XPathSelectElement

I have a XML file and loaded the specific tag <Acct> to an XElement. From this XElement in want to give a path to get the specific child <BIC> element. I don't wan't to use the Descendates() method. I tried using XPathSelectElement to get the job done but it always return null.
The XML Snippet i have looks something like this:
<Acct>
<Id>
<IBAN>TestIban</IBAN>
</Id>
<Ccy>EUR</Ccy>
<Svcr>
<FinInstnId>
<BIC>TestBic</BIC>
<ClrSysMmbId>
<ClrSysId>
<Cd>TestSysId</Cd>
</ClrSysId>
<MmbId>TestMemberId</MmbId>
</ClrSysMmbId>
<Nm>TestName</Nm>
<PstlAdr>
<AdrLine>TestAdrLine</AdrLine>
</PstlAdr>
<Othr>
<Id>OtherId</Id>
<Issr>Issr</Issr>
</Othr>
</FinInstnId>
</Svcr>
</Acct>
Like i said the XElement i have is the tag called acct. I tried now following to get the
<BIC> tag:
var bic = acct.XPathSelectElement("Svrc/FinInstnId/BIC");
var bic = acct.XPathSelectElement("/Svrc/FinInstnId/BIC");
var bic = acct.XPathSelectElement("./Svrc/FinInstnId/BIC");
var bic = acct.XPathSelectElement("Svrc//FinInstnId//BIC");
var bic = acct.XPathSelectElement("//Svrc//FinInstnId//BIC");
var bic = acct.XPathSelectElement(".//Svrc//FinInstnId//BIC");
var bic = acct.XPathSelectElement("Acct/Svrc/FinInstnId/BIC");
var bic = acct.XPathSelectElement("/Acct/Svrc/FinInstnId/BIC");
var bic = acct.XPathSelectElement("./Acct/Svrc/FinInstnId/BIC");
var bic = acct.XPathSelectElement("Acct//Svrc//FinInstnId//BIC");
var bic = acct.XPathSelectElement("//Acct//Svrc//FinInstnId//BIC");
var bic = acct.XPathSelectElement(".//Acct//Svrc//FinInstnId//BIC");
But all of these returning null. I found this article and they are doing in my point of view exactly the same:
https://codereview.stackexchange.com/questions/204464/get-a-xelement-at-a-given-path
SO my question is how do i use the XPathSelectElement method from my XElement to get a child like the tag as XElement?
Edit:
I inspected the XElement in Debug Mode with the Text Visualizer. The XML in the Element looks like the following (The values of the elements are different but this shouldn't change the problem):
<Acct xmlns="urn:iso:std:iso:20022:tech:xsd:camt.053.001.02">
<Id>
<IBAN>TestIban</IBAN>
</Id>
<Ccy>EUR</Ccy>
<Svcr>
<FinInstnId>
<BIC>TestBic</BIC>
<ClrSysMmbId>
<ClrSysId>
<Cd>Cd</Cd>
</ClrSysId>
<MmbId>TestMbmId</MmbId>
</ClrSysMmbId>
<Nm>SomeName</Nm>
<PstlAdr>
<AdrLine>Address</AdrLine>
</PstlAdr>
<Othr>
<Id>Id</Id>
<Issr>Issr</Issr>
</Othr>
</FinInstnId>
</Svcr>
</Acct>
Code works fine
var xmlString = #"<root>
<Acct>
<Id>
<IBAN>TestIban</IBAN>
</Id>
<Ccy>EUR</Ccy>
<Svcr>
<FinInstnId>
<BIC>TestBic</BIC>
<ClrSysMmbId>
<ClrSysId>
<Cd>TestSysId</Cd>
</ClrSysId>
<MmbId>TestMemberId</MmbId>
</ClrSysMmbId>
<Nm>TestName</Nm>
<PstlAdr>
<AdrLine>TestAdrLine</AdrLine>
</PstlAdr>
<Othr>
<Id>OtherId</Id>
<Issr>Issr</Issr>
</Othr>
</FinInstnId>
</Svcr>
</Acct>
</root>";
XDocument doc = XDocument.Parse(xmlString);
XElement acct = doc.XPathSelectElement("root/Acct");
XElement element = acct.XPathSelectElement("Svcr/FinInstnId/BIC");
Console.WriteLine(element.Value);
//print "TestBic"
are you sure acct contain right XElement?
update with namespace
XDocument doc = XDocument.Parse(xmlString);
var reader = doc.CreateReader();
XmlNamespaceManager nsmgr = new XmlNamespaceManager(reader.NameTable);
nsmgr.AddNamespace("ns", "urn:iso:std:iso:20022:tech:xsd:camt.053.001.02");
XElement acct = doc.XPathSelectElement("//ns:Acct", nsmgr);
XElement element = acct.XPathSelectElement("*[local-name() = 'Svcr']/*[local-name() = 'FinInstnId']/*[local-name() = 'BIC']");
var anotherWay = acct.XPathSelectElement("ns:Svcr/ns:FinInstnId/ns:BIC", nsmgr);
with local-name() you can ignore namespace

How to get value of some object in XML string in C#?

I have this XML String :
<RESPONSE>
<SINGLE>
<KEY name="sitename">
<VALUE>Stackoverflow</VALUE>
</KEY>
<KEY name="username">
<VALUE>this value</VALUE>
</KEY>
</SINGLE>
</RESPONSE>
How to get value from Key that name "username" ? I want to get value of "this value" in my code. I try deserialized and any other code but it doesnt work. Please help me, thanks :D
Edit:
I tried using this code :
XDocument doc = XDocument.Load( "myXML.xml" );
var keys = doc.Descendants( "KEY" );
foreach ( var VALUE in keys )
{
Console.WriteLine( VALUE.Value );
}
But how did I get the Value only from KEY that named "Username" ? Thanks :))
You can probably use an xpath to do this. The following is an example XPath that will provide a node with name matching "sitename":
//KEY[#name="sitename"]
You can modify this slightly to find all nodes with a "name" attribute or to just find specific names. For more examples of how to use XPath see the MSDN site for XPath. The following is a snippet of C# code that shows you how to use this XPath (again, you can generalize for whatever XPath you need):
const string example_xml = "<RESPONSE> <SINGLE> <KEY name=\"sitename\"> <VALUE>Stackoverflow</VALUE> </KEY> <KEY name=\"username\"> <VALUE>this value</VALUE> </KEY> </SINGLE> </RESPONSE>";
// load
XmlDocument doc = new XmlDocument();
doc.LoadXml(example_xml);
// Query single or multiple nodes using the XPath, do what you want with this node!
var desiredNode = doc.SelectSingleNode("//KEY[#name=\"sitename\"]");
Best of luck!
For completeness here is a System.Xml.Linq version, with the foreachs and where's being System.Linq for good measure. This basically the questioner's attempt, with a where to filter according to attribute.
const string example_xml = "<RESPONSE> <SINGLE> <KEY name=\"sitename\"> <VALUE>Stackoverflow</VALUE> </KEY> <KEY name=\"username\"> <VALUE>this value</VALUE> </KEY> </SINGLE> </RESPONSE>";
XDocument doc = XDocument.Parse(example_xml);
var keys = doc.Descendants("KEY");
var userKeys = keys.Where(item => item.Attribute("name").Value == "username").ToList();
userKeys.ForEach(item => Console.WriteLine(item.Value));
Lets consider your xml document as XYZ.xml, then you may try below code if you are using C#, below is the example only
XmlDocument Doc = new XmlDocument();
Doc.Load(Server.MapPath(".../xyz.xml"));
XmlNodeList itemList = Doc.DocumentElement.SelectNodes("KEY");
foreach (XmlNode currNode in itemList)
{
string name = string.Empty;
XmlNode item = currNode.SelectSingleNode("KEY");
if(currNode["name"].InnerText == "username")//if you are aware of key name, use this condition
{
name = item.Attributes["name"].Value.ToString(); // or currNode["name"].InnerText;
}
}

Parse through XML

I've been reading through many tutorials and examples, but I'm lost. I have an XML file with this type of data:
<?xml version="1.0"?>
<properties>
<property>
<name>Client Property A</name>
<phone>Client Property A Phone Number</phone>
</property>
<property>
<name>Client Property B</name>
<phone>Client Property B Phone Number</phone>
</property>
<property>
<name>Client Property C</name>
<phone>Client Property C Phone Number</phone>
</property>
</properties>
I'm trying to parse through this data in C# but having no luck at all. I have this:
XmlTextReader xmldata = new XmlTextReader("http://url.to/xml");
XmlNodeList xmllist = doc.GetElementsByTagName("property");
processList( xmllist );
public void processList(XmlNodeList xmllist)
{
// Loop through each property node and list the information
foreach (XmlNode node in xmllist)
{
XmlElement nodeElement = (XmlElement)node;
txtBox.AppendText(nodeElement.GetElementsByTagName("name")[0].InnerText);
txtBox.AppendText(nodeElement.GetElementsByTagName("phone")[0].InnerText);
}
}
But nothing gets output in to my text box. :(
You can use Linq to Xml to get properties from your xml:
var xdoc = XDocument.Load("http://url.to/xml");
foreach(var p in xdoc.Root.Elements("property"))
{
txtBox.AppendText((string)p.Element("name"));
txtBox.AppendText((string)p.Element("phone"));
}
var m_strFilePath = "http://www.google.com/ig/api?weather=12414&hl=it";
string xmlStr;
using(var wc = new WebClient())
{
xmlStr = wc.DownloadString(m_strFilePath);
}
var doc= new XmlDocument();
doc.LoadXml(xmlStr);
XmlNodeList xmllist = doc.SelectNodes("//property");
processList( xmllist );
public void processList(XmlNodeList xmllist)
{
// Loop through each property node and list the information
foreach (XmlNode node in xmllist)
{
XmlElement nodeElement = (XmlElement)node;
txtBox.AppendText(nodeElement.SelectSingleNode("name").InnerText);
txtBox.AppendText(nodeElement.SelectSingleNode("phone").InnerText);
}
}

Retrieving a Deeply Nested Value in an XML File

I'm trying to read a property in an XML file using C# and LINQ XML and I can't retrieve a value that is deeply nested in the tree. The value I'm trying to get is the contents of <Value> near <DisplayName>Add Your Comments</DisplayName>. Every <OrderProduct id=???> may have its own comments.
I can read other properties in the XML file using LINQ, but I'm confused how to go about reading something so deeply nested.
Thanks.
<?xml version="1.0" encoding="utf-16"?>
<OrderXml>
<Order>
<OrderProducts>
<OrderProduct id="1">
.
.
.
</OrderProduct>
<OrderProduct id="2">
<PropertyValues>
<PropertyValue>
<Property id="10786">
<DisplayName>Base</DisplayName>
</Property>
<Value />
</PropertyValue>
<PropertyValue>
<Property id="10846">
<DisplayName>Add Your Comments</DisplayName>
</Property>
<Value>this is a comment</Value>
</PropertyValue>
</PropertyValues>
</OrderProduct>
</OrderProducts>
</Order>
</OrderXml>
This is the code I have so far. I can retrieve the "Add Your Comments" part, but I'm stuck in how to get the part that follows it.
string productOrderID = "";
string productName = "";
XElement xelement;
xelement = XElement.Load (#"D:\Order.xml");
IEnumerable<XElement> Products = xelement.Descendants ("OrderProduct");
foreach (var order in Products)
{
productOrderID = order.Attribute ("id").Value;
productName = order.Element ("Product").Element ("Name").Value;
Console.WriteLine ("productOrderID: {0}", productOrderID);
Console.WriteLine ("productName: {0}", productName);
Console.WriteLine ("");
IEnumerable<XElement> PropertyValues = xelement.Descendants ("PropertyValues").Elements ("PropertyValue");
foreach (var propValue in PropertyValues.Elements ("Property").Elements ("DisplayName"))
{
Console.WriteLine ("Property ID: {0}", propValue.Value);
if (propValue.Value == "Add Your Comments")
{
Console.WriteLine ("---");
}
}
}
You can use Descendants to search for nodes in document no matter where they are:
string name = "Add Your Comments";
var value = xdoc
.Descendants("PropertyValue")
.Where(pv => (string)pv.Element("Property").Element("DisplayName") == name)
.Select(pv => (string)pv.Element("Value"))
.FirstOrDefault();
Output:
this is a comment

Parsing xml. return one object not collection

I have a xml file:
<Result>Ok</Result>
<Error></Error>
<Remark></Remark>
<Data>
<Movies>
<Movie ID='2'>
<Name><![CDATA[TestName]]></Name>
<Duration Duration='170'>2h 50min</Duration>
<Properties>
<Property Name='11'><![CDATA[1111110]]></Property>
</Properties>
<Rental from_date='' to_date=''>
<SessionCount></SessionCount>
<PU_NUMBER></PU_NUMBER>
</Rental>
</Movie>
</Movies>
</Data>
</XML>
Code for pasring xml file:
var results = from element in XDocument.Parse(queryResponse).Descendants("Movie")
select new BaseEvent
{
OID = (int)element.Attribute("ID"),
Subject = (string)element.Element("Name"),
Duration = (int)element.Element("Duration").Attribute("Duration")
};
The problem in that Descedants retruns IEumerable<BaseEvent> but I want that will be BaseEvent. How can I do this?
Just use First(), Last(), Single(), FirstOrDefault() etc.
Personally I'd do that initially, rather than doing it all in a query:
var element = XDocument.Parse(queryResponse)
.Descendants("Movie")
.FirstOrDefault();
if (element == null)
{
// Handle the case of no movies
}
else
{
var baseEvent = new BaseEvent
{
OID = (int) element.Attribute("ID"),
Subject = (string) element.Element("Name"),
Duration = (int) element.Element("Duration")
.Attribute("Duration")
};
// Use baseEvent
}
Add a .First() to get the first element:
from element in XDocument.Parse(queryResponse).Descendants("Movie")
select new BaseEvent
{
OID = (int)element.Attribute("ID"),
Subject = (string)element.Element("Name"),
Duration = (int)element.Element("Duration").Attribute("Duration")
}.First();
You can alternatively use FirstOrDefault() (in case there are no such nodes), Last() or Single().

Categories