I have XmlDocument object with next structure:
<ROOT>
<MESSAGE>
<some_fields />
<myDate>
<myParameter>
</MESSAGE>
<MESSAGE>
...
</ROOT>
I want to get all MESSAGE nodes where myDate>= given date and myParameter=given parameter.
I.e. something like:
MyDoc.SelectNodes("/ROOT/MESSAGE..")
Is it possible to do it using XPath?
=================
OK. myDate has already type xs:dateTime. But now I have next exception:
//MESSAGE[myDate < xs:dateTime(2012-06-22T11:17:44)]' has an invalid
qualified name.
Code is:
XmlNodeList nodeList = MyXmlDocument.SelectNodes("//MESSAGE[myDate < xs:dateTime(" + givenDateTime + ")]");
And it doesn't work even with
"//MESSAGE[xs:dateTime('2012-06-22T11:47:32')=xs:dateTime('2012-06-22T11:47:32')]"
Then I have System.Xml.XPath.XPathException:
Namespace Manager or XsltContext needed. This query has a prefix,
variable, or user-defined function.
It can be done purely in XPATH:
MyDoc.SelectNodes("//MESSAGE[xs:date(./myDate#text()) > xs:date('given date') and myParameter[text()='given parameter']]")
[untested]
I would recommend using LINQ.
You could have something like
var nodes = from node in XDoc.Root.Elements("MESSAGE")
where (DateTime)node.Element("myDate") >= DateTime.Now
select node;
This would select the node elements where the myDate time is the current DateTime or in the future. You may want to look further into XML parsing with LINQ. I find it to be the preferred method of XML parsing.
Another example for you:
var nodes = from node in XDoc.Root.Elements("MESSAGE")
where (DateTime)node.Element("myDate") >= DateTime.Now
&& node.Element("myParameter").Value == "whatever"
select node;
Yes, that is very much possible. Please go through the following link where you can get all operators u need.
http://msdn.microsoft.com/en-us/library/aa226440(v=sql.80).aspx
http://www.javabeat.net/2009/03/how-to-query-xml-using-xpath/
Related
<Block ID="Ar0010100" BOX="185 211 825 278" ELEMENT_TYPE="h1" SEQ_NO="0" />
This is an example from my XML code. In C# I need to store ONLY ID'S inside of a block element in one variable, and ONLY Box's inside of a block element. I have been trying to do this for two days, and I don't know how to narrow down my question.
XmlNodeList idList = doc.SelectNodes("/Block/ID");
doesn't work... Any version of doc.selectnode, doc.GetElementBy... doesn't return the right element/children/whatever you call it. I'm not able to find documentation that tells me what I'm trying to reference. i don't know if ID or BOX are children, if they're attributes or what. This is my first time using XML, and I can't seem to narrow down my problem.
You can simply use following code
XmlNodeList elemList = doc.GetElementsByTagName("Your Element");
for (int i = 0; i < elemList.Count; i++)
{
string attrVal = elemList[i].Attributes["ID"].Value;
}
Demo: https://dotnetfiddle.net/5PpNPk
the above code is taken from here Read XML Attribute using XmlDocument
The problem is that ID is actually neither child nor part.
It's a node's attribute. You can access it this way:
doc.SelectSingleNode("/Block").GetAttribute("ID")
// or
doc.SelectSingleNode("/Block").Attributes["ID"].Value
Of course, you can iterate through them:
foreach (XmlElement element in doc.SelectNodes("/Block"))
{
Console.WriteLine(element.GetAttribute("ID"));
}
You also can ensure that it contains ID attribute, so, you won't get NullReferenceException or other exception. Use the following XPath:
foreach (XmlElement element in doc.SelectNodes("/Block[#ID]"))
{
Console.WriteLine(element.GetAttribute("ID"));
}
Your attempted xpath tried to find <Block> element having child element <ID>. In xpath, you use # at the beginning of attribute name to reference an attribute, for example /Block/#ID.
Given a correct xpath expression as parameter, SelectNodes() and SelectSingleNode() are capable of returning attributes. Here is an example :
var xml = #"<Block ID=""Ar0010100"" BOX=""185 211 825 278"" ELEMENT_TYPE=""h1"" SEQ_NO=""0"" />";
var doc = new XmlDocument();
doc.LoadXml(xml);
XmlNodeList idList = doc.SelectNodes("/Block/#ID");
foreach(XmlNode id in idList)
{
Console.WriteLine(id.Value);
}
Demo
Good Evening All, and happy weekend!.
I have been trying all day to understand how to parse my simple XML file so I can understand it enough to write a personal project I want to work on.
I have been reading articles on this site and others but cannot get past where I am :(
My XML Document is ...
<XML>
<User>
<ID>123456789</ID>
<Device>My PC</Device>
</User>
<History>
<CreationTime>27 June 2013</CreationTime>
<UpdatedTime>29 June 2013</UpdatedTime>
<LastUsage>30 June 2013</LastUsage>
<UsageCount>103</UsageCount>
</History>
<Configuration>
<Name>Test Item</Name>
<Details>READ ME</Details>
<Enabled>true</Enabled>
</Configuration>
</XML>
I am trying to get the value in the details element (READ ME). Below is my code
// Start Logging Progress
Console.WriteLine("Test Application - XML Parsing and Creating");
Console.ReadKey();
// Load XML Document
XmlDocument MyDoc = new XmlDocument(); MyDoc.Load(#"E:\MyXML.XML");
// Select Node
XmlNode MyNode = MyDoc.SelectSingleNode("XML/Configuration/Details");
// Output Node Value
Console.WriteLine(String.Concat("Details: ", MyNode.Value));
// Pause
Console.ReadKey();
My console application is running and outputing "Target: " but not giving me the detail within the element.
Can somebody see why this is happening, and perhaps give me advice if I am completely off the wheel? I have no previous knowledge in reading XML files; hence where I am now :)
Thanks! Tom
With the your XPATH expression
// Select Node
XmlNode MyNode = MyDoc.SelectSingleNode("XML/Configuration/Details");
your are selection an element so the type of the MyNode will be XmlElement but the Value of an XmlElement is always null (see on MSDN) so you need to use XmlElement.InnerText or XmlElement.InnerXml isntead.
So the changed your code to
// Output Node Value
Console.WriteLine(String.Concat("Details: ", MyNode.InnerText));
Or you can select the content of an element with using the XPATH text() function, in this case MyNode will be XmlText where you get its value with Value:
// Select Node
XmlNode MyNode = MyDoc.SelectSingleNode("XML/Configuration/Details/text()");
// Output Node Value
Console.WriteLine(String.Concat("Details: ", MyNode.Value));
As a sidenote if you are anyway learning XML manipulation in C# you should check out LINQ to XML which is another/newer way to working with XML in C#.
Just for interest, a little-known "simple" syntax is this:
XmlDocument myDoc = new XmlDocument();
myDoc.Load(#"D:\MyXML.XML");
string details = myDoc["XML"]["Configuration"]["Details"].InnerText;
Note that this (and the XPath approach) could go pop if your XML doesn't conform to the structure you're expecting, so you'd ideally put some validation in there as well.
U can use Xpath library for that (u must include "System.Xml.XPath"):
XmlDocument document = new XmlDocument();
document.Load("MyXml.xml");
XPathNavigator navigator = document.CreateNavigator();
foreach (XPathNavigator nav in navigator.Select("//Details"))
{
Console.WriteLine(nav.Value);
}
the above code iterate over every node called (Details) extracting information and print it.
If you want to retrieve a particular value from an XML file
XmlDocument _LocalInfo_Xml = new XmlDocument();
_LocalInfo_Xml.Load(fileName);
XmlElement _XmlElement;
_XmlElement = _LocalInfo_Xml.GetElementsByTagName("UserId")[0] as XmlElement;
string Value = _XmlElement.InnerText;
Value contains the text value
Load function is already defined in xmlData class
public class XmlData
{
public void Load(XElement xDoc)
{
var id = xDoc.XPathSelectElements("//ID");
var listIds = xDoc.XPathSelectElements("/Lists//List/ListIDS/ListIDS");
}
}
I'm just calling the Load function from my end.
XmlData aXmlData = new XmlData();
string input, stringXML = "";
TextReader aTextReader = new StreamReader("D:\\test.xml");
while ((input = aTextReader.ReadLine()) != null)
{
stringXML += input;
}
XElement Content = XElement.Parse(stringXML);
aXmlData.Load(Content);
in load function,im getting both id and and listIds as null.
My test.xml contains
<SEARCH>
<ID>11242</ID>
<Lists>
<List CURRENT="true" AGGREGATEDCHANGED="false">
<ListIDS>
<ListID>100567</ListID>
<ListID>100564</ListID>
<ListID>100025</ListID>
<ListID>2</ListID>
<ListID>1</ListID>
</ListIDS>
</List>
</Lists>
</SEARCH>
EDIT: Your sample XML doesn't have an id element in the namespace with the nss alias. It would be <nss:id> in that case, or there'd be a default namespace set up. I've assumed for this answer that in reality the element you're looking for is in the namespace.
Your query is trying to find an element called id at the root level. To find all id elements, you need:
var tempId = xDoc.XPathSelectElements("//nss:id", ns);
... although personally I'd use:
XDocument doc = XDocument.Parse(...);
XNamespace nss = "http://schemas.microsoft.com/SQLServer/reporting/reportdesigner";
// Or use FirstOrDefault(), or whatever...
XElement idElement = doc.Descendants(nss + "id").Single();
(I prefer using the query methods on LINQ to XML types instead of XPath... I find it easier to avoid silly syntax errors etc.)
Your sample code is also unclear as you're using xDoc which hasn't been declared... it helps to write complete examples, ideally including everything required to compile and run as a console app.
I am looking at the question 3 hours after it was submitted and 41 minutes after it was (last) edited.
There are no namespaces defined in the provided XML document.
var listIds = xDoc.XPathSelectElements("/Lists//List/ListIDS/ListIDS");
This XPath expression obviously doesn't select any node from the provided XML document, because the XML document doesn't have a top element named Lists (the name of the actual top element is SEARCH)
var id = xDoc.XPathSelectElements("//ID");
in load function,im getting both id and and listIds as null.
This statement is false, because //ID selects the only element named ID in the provided XML document, thus the value of the C# variable id is non-null. Probably you didn't test thoroughly after editing the XML document.
Most probably the original ID element belonged to some namespace. But now it is in "no namespace" and the XPath expression above does select it.
string xmldocument = "<response xmlns:nss=\"http://schemas.microsoft.com/SQLServer/reporting/reportdesigner\"><action>test</action><id>1</id></response>";
XElement Content = XElement.Parse(xmldocument);
XPathNavigator navigator = Content.CreateNavigator();
XmlNamespaceManager ns = new XmlNamespaceManager(navigator.NameTable);
ns.AddNamespace("nss", "http://schemas.microsoft.com/SQLServer/reporting/reportdesigner");
var tempId = navigator.SelectSingleNode("/id");
The reason for the null value or system returned value is due to the following
var id = xDoc.XPathSelectElements("//ID");
XpathSElectElements is System.xml.linq.XElment which is linq queried date. It cannot be directly outputed as such.
To Get individual first match element
use XPathSelectElement("//ID");
You can check the number of occurrences using XPathSelectElements as
var count=xDoc.XPathSelectElements("//ID").count();
you can also query the linq statement as order by using specific conditions
Inorder to get node value from a list u can use this
foreach (XmlNode xNode in xDoc.SelectNodes("//ListIDS/ListID"))
{
Console.WriteLine(xNode.InnerText);
}
For Second list you havnt got the value since, the XPath for list items is not correct
I am parsing an URI for query_id. I want to get the last query's id. That is actually the last added node in the URI.
I am using the following code but it is failing to return the last node but is returning info from the first node. HELP !!!
XmlDocument doc = new XmlDocument();
doc.Load("helpdesk.hujelabs.com/user.php/1/query");
XmlNode node = doc.DocumentElement;
XmlNode id = node.LastChild.SelectSingleNode("//queries/query/description/text()");
string TID = id.InnerText;
Any answer of the form:
//queries/query[position() = last()]/query_id/text()
or
//queries/query/description[last()]/text()
is wrong.
It is a FAQ: The XPath // pseudo-operator has lower precedence then the [] operator -- this is why the above expressions select any query (or respectively description) element that is the last child of its parent -- these can be all query or description elements.
Solution:
Use:
(//queries/query)[last()]/query_id/text()
Also note: The use of the // pseudo-operator usually results in signifficant loss of efficiency, because this causes the whole (sub) tree rooted at the current node to be completely traversed (O(N^2) operation).
A golden rule: Whenever the structure of the XML document is statically (in advance) known and stable, never use //. Instead use an XPath expression that has a series of specific location steps.
For example, if all the elements you want to select can be selected using:
/x/y/queries/query
then use the above XPath expression -- not //queries/query
use this XPath
//queries/query/description[last()]/text()
To retrieve last query's query_id, change your XPath to
/queries/query[position() = last()]/query_id/text()
Or alternatively, use LINQ to XML:
var doc = XDocument.Load("http://helpdesk.hujelabs.com/user.php/1/query");
var elem = doc.Root.Elements("query").Last().Element("query_id");
var TID = (int)elem;
Given the following XML, what query can I use to extract the value of preapprovalKey to a string variable? Still a little new to LINQ to XML.
<?xml version="1.0" encoding="UTF-8" ?>
- <ns2:PreapprovalResponse xmlns:ns2="http://svcs.paypal.com/types/ap">
- <responseEnvelope>
<timestamp>2011-04-05T18:35:32.952-07:00</timestamp>
<ack>Success</ack>
<correlationId>7cec030fa3eb2</correlationId>
<build>1655692</build>
</responseEnvelope>
<preapprovalKey>PA-9AG427954Y7578617</preapprovalKey>
</ns2:PreapprovalResponse>
XDocument doc = XDocument.Load("test.xml");
string preapprovalKey = doc.Descendants("preapprovalKey").Single().Value;
See below my exmaple, it help you to resolve your issue and problem. :)
Consider this below XML is there as one of the SQL table's column.
<Root>
<Name>Dinesh</Name>
<Id>2</Id>
</Root>
The objective of the query is to fetch the Name from the XML. In this example we will fetch the 'Dinesh' as the value.
var Query = (from t in dbContext.Employee.AsEnumerable()
where t.active == true
select new Employee
{
Id = t.AtpEventId,
Name = XDocument.Parse(t.Content).Descendants("Root").Descendants("Name").ToList().
Select(node => node.Value.ToString()).FirstOrDefault()
});
Note the following :-
Here in above LINQ , t.active == true is just an example to make some condition if needed.
Please note, in the above LInQ query, always use the AsEnumerable(), as I did in the
first file of the Linq query.exmaple(var Query = (from t in dbContext.Employee.AsEnumerable())
Descendants("Root").Descendants("Name") , Here Root should be the Element matching with the XML, And under the Root we have Name element, thats why we wrote
Descendants("Root").Descendants("Name")
For any further clarification you can reach me via danish.eggericx#gmail.com