How to get the xml node value in a string.
i am getting This error
Data at the root level is invalid. Line 1, position 1.
error shown in this line
xmldoc.LoadXml(xmlFile);
my xml
<?xml version="1.0" encoding="utf-8" ?>
<UOM>
<!-- The selected currency used will be stored here for Code reference" -->
<ActiveCurrencyType>
<ActiveCurrency>U.S.Dollar</ActiveCurrency>
<ActiveCode>USD</ActiveCode>
<ActiveSymbol>$</ActiveSymbol>
</ActiveCurrencyType>
<!-- The selected Dimension used will be stored here for Code reference -->
<ActiveDimension>
<ActiveDimensionUOM>Inches</ActiveDimensionUOM>
<ActiveDimensionSymbol>.in</ActiveDimensionSymbol>
</ActiveDimension>
<!-- The selected weight used will be stored here for Code reference -->
<ActiveWeight>
<ActiveWeightUOM>Pounds</ActiveWeightUOM>
<ActiveWeightSymbol>lb</ActiveWeightSymbol>
</ActiveWeight>
</UOM>
C# code
string xmlFile = Server.MapPath("~/HCConfig/HCUOM.xml");
XmlDocument xmldoc = new XmlDocument();
xmldoc.LoadXml(xmlFile);
XmlNodeList nodeList = xmldoc.GetElementsByTagName("ActiveDimensionSymbol");
string ActiveDimensionSymbol = string.Empty;
foreach (XmlNode node in nodeList)
{
ActiveDimensionSymbol = node.InnerText;
}
How can I achieve this?
You're using the wrong overload, LoadXml doesn't do what you think it does.
Use xmldoc.Load(xmFile); because that method takes an file path as input. LoadXml expects an string with xml in it.
The exception is an indicator of that mistake. What is processed is not XML, and a filepath isn't that.
After this changes the string ActiveDimensionSymbol contains .in if I run this locally.
If you want to use LoadXml you should first read your whole file in a string, for example like so:
xmldoc.LoadXml(File.ReadAllText(xmlFile));
but is really only overhead to call File.ReadAllText if there is an method that accepts a file.
You can use the Descendants() method to get all XElements by certain name, found in the System.Xml.Linq namespace.
XDocument doc = XDocument.Load("XMLFile1.xml");
string[] allActiveWeightUOMs = doc.Descendants("ActiveWeightUOM").Select(o => o.Value).ToArray();
// allActiveWeightUOMs : "Pounds" ...
As can seen here link the method that you are using to load the XML excepts xml by string not xml file. You can use XmlDocument.Load instead of XmlDocument.LoadXml
Try this code its works just fine with this xml
string xmlFile = Server.MapPath("~/HCConfig/HCUOM.xml");
XDocument doc = XDocument.Load(xmlFile );
var nodeList = doc.Descendants("ActiveDimensionSymbol");
string ActiveDimensionSymbol = string.Empty;
foreach (var node in nodeList)
{
ActiveDimensionSymbol = node.Value;
}
Related
I have a service which returns the below xml as string.I am using Xdocument parse method and XmlDocument load methods to convert the string to xml. but i want to parse and get the status and i_numer which i need to use for further processing.can some one point me in right direction or give some hints.below is the xml i am using.
i tried the innerxml property from the Xdocument and XmlDocument which is returning the whole "" element and this is not what i needed.
<Report>
<Incidentreport Company="company1" ID="sample">
<status i_number="12345678" status="sucessful" />
</Incidentreport>
</Report>
The following should work:
string str = [string of xml goes here];
string i_number = string.Empty;
XmlDocument doc = new XmlDocument();
doc.Load(str);
XmlNode node = doc.SelectSingleNode("//status");
i_number = node.Attributes["i_number"].Value;
You can use SelectSingleNode() which accept XPath parameter to get the target attribute value in one go * :
var raw = #"<Report>
<Incidentreport Company='company1' ID='sample'>
<status i_number='12345678' status='sucessful' />
</Incidentreport>
</Report>";
var doc = new XmlDocument();
doc.LoadXml(raw);
var result = doc.SelectSingleNode("/Report/Incidentreport/status/#i_number");
Console.WriteLine(result.Value);
dotnetfiddle demo
*) notice how XML attribute can be referenced by using #attribute_name syntax in XPath
I have an string parameter with xml content in it. Basically the string have an XML inside.
string S = funcThatReturnsXML (parameters);
S have the next text:
<?xml version="1.0" encoding="utf-8" ?>
<tagA>
<tagB>
<tagBB>
..
.
.
</tagBB>
.
.
</tagB>
<tagC>
..
..
.
</tagC>
</tagA>
The funcThatReturnsXML (parameters) creates an XmlDocument object but the return it as a string, I cant change this function, to much stuff works with it.
Tried to create XmlDocument objetc but the SelectSingleNode return null.
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(S);
XmlNode root = xmlDoc.SelectSingleNode("tagB");
How can I delete from string S (not XML Object) specific node, for example <tagB>
EDIT: this is the XML I tested with:
<?xml version="1.0" ?>
- <Request xmlns:xsi="http://www.mysite.com" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
- <info xmlns="http://www.mysite.com">
<RequestTR>54</RequestTR>
<time>2013-12-22</time>
</info>
- <Parameters xmlns="http://www.mysite.com">
<id>3</id>
<name>2</name>
</Parameters>
<title>Request</title>
</Request>
Try this:
string S = funcThatReturnsXML(parameters);
var doc = XDocument.Parse(S);
var nodeToRemove = doc.Descendants("tagB");
nodeToRemove.Remove();
That will remove all nodes named "tagB" from string S which contains xml.
UPDATE 1:
Sorry, i missed to include one more line:
S = doc.ToString();
My first code above removed "tagB" from doc but didnt save it back to S variable.
UPDATE 2:
I tested with following xml which contain attribute:
<tagA attribute="value">
<tagB>
<tagBB>
</tagBB>
</tagB>
<tagC></tagC>
</tagA>
and the output of Console.WriteLine(S):
<tagA attribute="value">
<tagC></tagC>
</tagA>
UPDATE 3:
Given your updated xml format, I know why my previous code didn't work for you. That was because your xml have namespace (xmlns) declared. The solution is to use LocalName when searching for the node to be removed, that will search for node name while ignoring its namespace. The follwoing example shows how to remove all "info" node:
var doc = XDocument.Parse(S);
var nodeToRemove = doc.Descendants().Where(o => o.Name.LocalName == "info");
nodeToRemove.Remove();
S = doc.ToString();
If you can determine the particular outer element to remove from the returned XML, you could use LINQ to XML:
var returnedXml = funcThatReturnsXML(parameters);
var xmlElementToRemove = funcThatReturnsOuterElement(returnedXml);
var xelement = XElement.Load("XmlDoc.txt");
xelement.Elements().Where(e => e.Name == xmlElementToRemove).Remove();
For example:
using System.Linq;
using System.Xml.Linq;
class Program
{
static void Main(string[] args)
{
// pretend this is the funThatReturnsXML return value
var returnedXml = "<tagB><tagBB></tagBB></tagB>";
// get the outer XML element name
var xmlElementToRemove = GetOuterXmlElement(returnedXml);
// load XML from where ever
var xelement = XElement.Load("XmlDoc.txt");
// remove the outer element and all subsequent elements
xelement.Elements().Where(e => e.Name == xmlElementToRemove).Remove();
}
static string GetOuterXmlElement(string xml)
{
var index = xml.IndexOf('>');
return xml.Substring(1, index - 1);
}
}
Note that the above is a "greedy" removal method, if there is more than once element with the name returned via the GetOuterXmlElemet method they will all be removed. If you want a specific instance to be removed then you will require something more sophisticated.
Building on your edit:
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(S);
var nodeA = xmlDoc.SelectSingleNode("/tagA");
var nodeB = nodeA.SelectSingleNode("tagB");
nodeA.RemoveChild(nodeB);
To remove (possibly) multiple tagB nodes in unknown positions, you may try:
var bees = xmlDoc.SelectNodes("//tagB");
foreach (XmlNode bee in bees) {
var parent = bee.ParentNode;
parent.RemoveChild(bee);
}
The xml is coming from a url and all I need is the pull the string "N0014E1" from it. I am not sure why this code is not working. I put a try block around it and I get a "Data root level is invalid"
xml:
<obj is="c2g:Network " xsi:schemaLocation="http://obix.org/ns/schema/1.0/obi/xsd" href="http://192.168.2.230/obix/config/">
<ref name="N0014E1" is="c2g:LOCAL c2g:Node"xsi:schemaLocation="http://obix.org/ns/sc/1.0/obix/xsd" href="N0014E1/"></ref>
</obj>
C# code:
public static string NodePath = "http://" + MainClass.IpAddress + ObixPath;
public static void XMLData()
{
XmlDocument NodeValue = new XmlDocument();
NodeValue.LoadXml(NodePath);
var nodes = NodeValue.SelectNodes(NodePath);
foreach (XmlNode Node in nodes)
{
HttpContext.Current.Response.Write(Node.SelectSingleNode("//ref name").Value);
Console.WriteLine(Node.Value);
}
//Console.WriteLine(Node);
Console.ReadLine();
}
Your SelectNodes and SelectSingleNode commands are incorrect. Both expect an xpath string to identify the node.
Try the following
string xml = #"<obj is=""c2g:Network "" href=""http://192.168.2.230/obix/config/""><ref name=""N0014E1"" is=""c2g:LOCAL c2g:Node"" href=""N0014E1/""></ref></obj>";
XmlDocument NodeValue = new XmlDocument();
NodeValue.LoadXml(xml);
XmlNode r = NodeValue.SelectSingleNode("//ref[#name]");
if (r != null)
{
System.Diagnostics.Debug.WriteLine(r.Attributes["name"].Value);
}
Also, Note, that LoadXml method simply loads an xml string; it will not load from a remote url.
As #kevintdiy has pointed out your xml is not entirely correct. In the sample above I have stripped out the xsi reference as you are lacking a definition for it.
If you have access to the source xml, either remove the reference to xsi if its not required or add a definition for it to the root node.
If this is not possible, then you may want to consider using regular expression or other string based methods for getting the value.
I have a XML file, that looks like this inside:
<Data>
<INFO>
..
...
<JOB_NAME value="filename.pdf"/>
<useless_info value="some_info"/>
<TIMESTAMP value="20120210075304"/>
<more_useless_info value="012345"/>
...
..
</INFO>
<INFO>
..
...
<JOB_NAME value="filename2.pdf"/>
<useless_info value="some_info"/>
<TIMESTAMP value="20120210073487"/>
<more_useless_info value="012345"/>
...
..
</INFO>
</Data>
What i want to do, is write specific info to strings, so that later on i can write these to a text file or new XML file.
I found this example here: http://www.csharp-examples.net/xml-nodes-by-name/
And i have this code a little bit working.
Not fully, because it it not getting the values.
my code looks like this:
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(FileNameTextBox.Text);
XmlNodeList xnList = xmlDoc.SelectNodes("/Data/INFO");
foreach (XmlNode xn in xnList)
{
string jobName = xn["JOB_NAME"].InnerText;
string timeStamp = xn["TIMESTAMP"].InnerText;
MessageBox.Show(timeStamp + jobName); //for testing
}
I think this has to do with the fact that the info that i want to get, is not boxed in like <box>info</box>
What i cant find is how i could get the info in my caseout of the xml file now.
Could someone lent me a hand?
thank you!
You need to select the JOB_NAME and TIMESTAMP child nodes of each INFO node, then get their attributes, then get the Value of the "value" attribute.
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(FileNameTextBox.Text);
XmlNodeList xnList = xmlDoc.SelectNodes("/Data/INFO");
foreach (XmlNode xn in xnList)
{
string jobName = xn.SelectSingleNode("JOB_NAME").Attributes["value"].Value;
string timeStamp = xn.SelectSingleNode("TIMESTAMP").Attributes["value"].Value;
MessageBox.Show(timeStamp + jobName); //for testing
}
Be careful with this though as you are likely to get a NullReferenceException if any of the INFO nodes don't contain both a JOB_NAME and TIMESTAMP Node, and also if either of those do not have an attribute "value".
To answer your comment below:
string vendorName = xn.SelectSingleNode("JOB_NAME").Attributes["vendor-name"].Value;
string mediaName = xn.SelectSingleNode("JOB_NAME").Attributes["media-name"].Value;
You're correct in that innerText won't work because in your example 'value' is an attribute.
string jobName = xn["JOB_NAME"].Attributes["value"].Value;
string timeStamp = xn["TIMESTAMP"].Attributes["value"].Value;
Corrected and tested. This method or the SelectSingleNode should work fine.
If you want to iterate over all INFO elements and read the contained JOB_NAME and TIMESTAMPs valueattributes then Tobsey's answer is correct and will give you the desired result.
If you intend to query specific values from your Xml document you should use XPath queries instead of iterating over a set of nodes:
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(FileNameTextBox.Text);
string jobName = xmlDoc.SelectSingleNode("//JOB_NAME/#value").Value;
string timeStamp = xmlDoc.SelectSingleNode("//TIMESTAMP/#value").Value;
Update
If you have repeating INFO nodes but just are interested in the first one you could change your query to just look at the first one:
string jobName = xmlDoc.SelectSingleNode("//INFO[1]/JOB_NAME/#value").Value;
string timeStamp = xmlDoc.SelectSingleNode("//INFO[1]/TIMESTAMP/#value").Value;
The Xpath query //INFO[1]/JOB_NAME/#value is a shorthand expression for //INFO[position() = 1]/JOB_NAME/#value and will examine the position of the node in your Xml document.
Beware! The simplified example above will fail if .SelectSingleNode returns null!
You should get the Value property of the attribute named "value" in your nodes:
string jobName = xn.SelectSingleNode("JOB_NAME").Attributes["value"].Value;
<?xml version="1.0" encoding="UTF-8"?>
<form:Documents xmlns:form="http://www.abbyy.com/FlexiCapture/Schemas/Export/FormData.xsd" xmlns:addData="http://www.abbyy.com/FlexiCapture/Schemas/Export/AdditionalFormData.xsd">
<_Document_Definition_1:_Document_Definition_1 addData:ImagePath="C:\POC\Export\Test.pdf" xmlns:_Document_Definition_1="http://www.abbyy.com/FlexiCapture/Schemas/Export/Document_Definition_1.xsd">
<_Page_1>
<_First_Name>John</_First_Name>
<_Last_Name>Doe</_Last_Name>
</_Page_1>
</_Document_Definition_1:_Document_Definition_1>
</form:Documents>
I have xml containing directory of pdf file which I would need to read.
I can read first name and last name from _Page_1 node but do not know how to read ImagePath.
Here is my code to read from _Page_1
XDocument xDoc = XDocument.Load("Test.xml");
var poc = from p in xDoc.Descendants("_Page_1")
select new
{
FirstName = p.Element("_First_Name").Value,
LastNumber = p.Element("_Last_Name").Value
};
// Execute the query
foreach (var customer in poc)
{
Console.WriteLine(customer.FirstName);
Console.WriteLine(customer.LastName);
}
//Pause the application
Console.ReadLine();
Thank you BrokenGlass, it's working.
I have one more question.
What if I have several iteration of _Document_Definition node, how do I read each iteration.
<?xml version="1.0" encoding="UTF-8"?>
<form:Documents xmlns:form="http://www.abbyy.com/FlexiCapture/Schemas/Export/FormData.xsd" xmlns:addData="http://www.abbyy.com/FlexiCapture/Schemas/Export/AdditionalFormData.xsd">
<_Document_Definition_1:_Document_Definition_1 addData:ImagePath="C:\POC\Export\Test.pdf" xmlns:_Document_Definition_1="http://www.abbyy.com/FlexiCapture/Schemas/Export/Document_Definition_1.xsd">
<_Page_1>
<_First_Name>John</_First_Name>
<_Last_Name>Doe</_Last_Name>
</_Page_1>
</_Document_Definition_1:_Document_Definition_1>
<_Document_Definition_1:_Document_Definition_1 addData:ImagePath="C:\POC\Export\Test2.pdf" xmlns:_Document_Definition_1="http://www.abbyy.com/FlexiCapture/Schemas/Export/Document_Definition_1.xsd">
<_Page_1>
<_First_Name>Jane</_First_Name>
<_Last_Name>Doe</_Last_Name>
</_Page_1>
</_Document_Definition_1:_Document_Definition_1>
</form:Documents>
You are missing the XML namespace references to access those attributes, this works:
XDocument doc = XDocument.Load(#"test.xml");
XNamespace _Document_Definition_1 = "http://www.abbyy.com/FlexiCapture/Schemas/Export/Document_Definition_1.xsd";
XNamespace addData = "http://www.abbyy.com/FlexiCapture/Schemas/Export/AdditionalFormData.xsd";
string impagePath = doc.Descendants(_Document_Definition_1 + "_Document_Definition_1")
.First()
.Attribute(addData + "ImagePath")
.Value;
It looks like Imagepath is an attribute not an element. Hence you are not able to read it. Check for the attributes in the xml file.