I have some XML that looks like this:
<PackageConstruct900 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<ID>{5209724e-1c5a-4d84-962e-371271c3836c}</ID>
<ParentID />
<Name />
<Type>Package</Type>
<Tasks>
<anyType xsi:type="Task">
<ID>{4c97132c-ba7d-4fba-9b01-333976e9ad22}</ID>
<ParentID>{E893A7FD-2758-4315-9181-93F8728332E5}</ParentID>
<Name>ProcessAgility</Name>
<Type>Task</Type>
<StartedOn>1900-01-01T00:00:00</StartedOn>
<EndedOn>1900-01-01T00:00:00</EndedOn>
</anyType>
</Tasks>
</PackageConstruct900>
I'm trying to capture the Value of the second "Name" node ("ProcessAgility").
But (XmlReader) reader.Value returns an empty string when I arrive at this node. How do I capture the TEXT that falls betweeen <nodeName>TEXT</nodeName> ?
Here's my code so far:
XmlReader reader = XmlReader.Create(pathToFile, settings);
reader.MoveToContent();
while (reader.Read())
{
switch (reader.NodeType)
{
case XmlNodeType.Text:
break;
case XmlNodeType.Element:
switch (reader.Name)
{
case "anyType":
newJob = true;
break;
case "AML":
string ss = string.Empty;
ss = reader.ReadInnerXml();
ss = System.Net.WebUtility.HtmlDecode(ss);
rs = XmlReader.Create(ss, settings);
break;
case "Name":
if (newJob && reader.HasValue)
{
jobName = reader.Value;
}
if (!string.IsNullOrWhiteSpace(jobName))
{
if (!jobsAdded.Contains(jobName))
{
jobsAdded.Add(jobName);
}
}
break;
case "Tasks":
m_ConvertingTask = true;
break;
case "TRIGGERS":
break;
}
break;
}
}
Try using XmlDocument then you can use XPath navigation like this: /PackageConstruct900/Tasks/anyType/Name
XmlDocument doc = new XmlDocument();
doc.LoadXml("<PackageConstruct900 xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">\r\n <ID>{5209724e-1c5a-4d84-962e-371271c3836c}</ID>\r\n <ParentID />\r\n <Name />\r\n <Type>Package</Type>\r\n <Tasks>\r\n <anyType xsi:type=\"Task\">\r\n <ID>{4c97132c-ba7d-4fba-9b01-333976e9ad22}</ID>\r\n <ParentID>{E893A7FD-2758-4315-9181-93F8728332E5}</ParentID>\r\n <Name>ProcessAgility</Name>\r\n <Type>Task</Type>\r\n <StartedOn>1900-01-01T00:00:00</StartedOn>\r\n <EndedOn>1900-01-01T00:00:00</EndedOn>\r\n </anyType>\r\n </Tasks>\r\n</PackageConstruct900>");
XmlNode root = doc.DocumentElement;
XmlNode node = root.SelectSingleNode(
"/PackageConstruct900/Tasks/anyType/Name");
Console.WriteLine(node.InnerXml);
This will give you the first node, if you want the list then iterate it you can use:
XmlNodeList nodes = root.SelectNodes("/PackageConstruct900/Tasks");
foreach (XmlNode node in nodes)
{
var typename = node.SelectSingleNode("anyType/Name");
Console.WriteLine(typename.InnerXml);
}
A pretty simple (and very specific) System.Xml.Linq.XElement solution would be:
string processAgility = XElement.Parse(File.ReadAllText(pathToFile))
.Element("Tasks")
.Element("anyType")
.Element("Name")
.Value;
Or if you include a using System.Xml.XPath directive, you could use XPath natigation with the XPathSelectElement extension method:
string processAgility = XElement.Parse(File.ReadAllText(pathToFile))
.XPathSelectElement("Tasks/anyType/Name")
.Value;
Related
I have problem parse XML in C# because XML not have root element.
How can I add root element? When try XDocument show erorrs about root element.
Maybe can use some file stream?
Example:
<data>
<datetime>29.06.2020 10:15:15</datetime>
<Lenght/>
<Width>3</Width>
<Height>2</Height>
</data>
<data>
<datetime>29.06.2020 10:15:01</datetime>
<Lenght>1</Lenght>
<Width>2</Width>
<Height>3</Height>
</data>
My code:
XmlDocument report = new XmlDocument();
report.Load(fileOfReport); //there show error about root element
XmlElement root = report.CreateElement("root");
var items = report.GetElementsByTagName("data");
for (int i = 0; i < items.Count; i++)
{
root.AppendChild(items[i]);
}
report.AppendChild(root);
report.SaveAs(fileOfReport);
You can try the following solution.
Lots of minutiae string handling, but seems to be working for your case. XmlNodeType enumerator has 18 entries total. Your XML is relatively simple, that's why the switch has just 3 node types in the code. You can use StringBuilder instead of string data type while composing a well-formed XML.
void Main()
{
const string FILENAME = #"e:\temp\NoRootFile.xml";
const string NEWFILENAME = #"e:\temp\NoRootFileFixed.xml";
string xmlString = "<root>";
XmlReaderSettings settings = new XmlReaderSettings();
settings.ConformanceLevel = ConformanceLevel.Fragment;
using (XmlReader xr = XmlReader.Create(FILENAME, settings))
{
while (xr.Read())
{
if (xr.NodeType != XmlNodeType.XmlDeclaration)
{
switch (xr.NodeType)
{
case XmlNodeType.Element:
xmlString += "<" + xr.Name + ((xr.IsEmptyElement) ? "/>" : ">");
break;
case XmlNodeType.Text:
xmlString += xr.Value;
break;
case XmlNodeType.EndElement:
xmlString += "</" + xr.Name + ">";
break;
}
}
}
}
xmlString += "</root>";
XDocument xdoc = XDocument.Parse(xmlString);
xdoc.Save(NEWFILENAME);
}
I want to know how to get attribute "text" via c#?
Example xml:
<?xml version="1.0" encoding="utf-8" ?>
<Model Name="modelname">
<Mode Name="text">
<Class>Class1</Class>
</Mode>
</Model>
I try to parse this xml by using XMLReader(example from msdn) :
while (reader.Read())
{
switch (reader.NodeType)
{
case XmlNodeType.Element:
Console.Write("<" + reader.Name+"");
Console.WriteLine(str);
if (reader.Name =="Mode")
{
namemode = true;
}
if (namemode)
{
if (reader.Name == element)
{
elementExists = true;
}
}
// Console.WriteLine(">");
break;
case XmlNodeType.Text:
Console.WriteLine(reader.Value);
if (elementExists)
{
values.Add(reader.Value);
elementExists = false;
}
break;
}
}
Maybe i should use XMLDocument to do this?
Thanks.
You could use XDocument and LINQ
You'll need to include the System.Xml.Linq.XDocument namespace.
Then you could do something like:
XDocument document = XDocument.Load(filePath);
var modes = (from modes in document.Root.Descendants("Mode")
select modes.Attribute("Name").Value).ToList();
Like this:
const string xml = #"<?xml version=""1.0"" encoding=""utf-8"" ?>
<Model Name=""modelname"">
<Mode Name=""text"">
<Class>Class1</Class>
</Mode>
</Model>";
XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);
Console.WriteLine(doc.DocumentElement["Mode"].Attributes["Name"].Value);
I'm having program like below. The concept is Read XML value from URL, but my program read the xml structure only, not the code datas. Like <Billing Address></Billing Address>... etc only. But the original XML value is <Billing Address>Strre1</Billing Address>. The Program does not read the inside value.
public static void zohoCRMReadAccounts()
{
var val = auth();
var val1= val[0];
var val2= val[1];
String xmlURL = "URL";
XmlTextReader xmlReader = new XmlTextReader(xmlURL);
while (xmlReader.Read())
{
switch (xmlReader.NodeType)
{
case XmlNodeType.Element: // The node is an element.
Console.Write("<" + xmlReader.Name);
// Read the attributes:
while (xmlReader.MoveToNextAttribute())
Console.Write(" " + xmlReader.Name + "=’"
+ xmlReader.Value + "’");
Console.WriteLine(">");
break;
case XmlNodeType.Text: //Display the text in each element.
Console.WriteLine(xmlReader.Value);
break;
case XmlNodeType.EndElement: //Display the end of the element.
Console.Write("</" + xmlReader.Name);
Console.WriteLine(">");
break;
}
}
Console.WriteLine("Press any key to continue…");
Console.ReadLine(); //Pause
}
Please help me to fix
XML Elements cannot have spaces in their names. Try to remove them first
First download the XML. Then Use like,
try {
//read xml
XmlDocument xdoc = new XmlDocument();
xdoc.Load("XMLFilePath");
XmlNodeList nodes = xdoc.SelectNodes(#"rss/channel/item");
foreach (XmlNode node in nodes)
{
XmlNode titleNode = node.SelectSingleNode("title");
string title = titleNode == null ? string.Empty : titleNode.InnerText;
};
}
This is the XML that i want to read.
<Server ServerName="SP-SWD-T01">
Some nodes are there
</Server>
I want to read the ServerName inside the server how can i read it.Please help.
This is the code
XmlReaderSettings readerSettings = new XmlReaderSettings();
readerSettings.IgnoreComments = false;
XmlReader xmlRdr = XmlReader.Create(strFilePath, readerSettings);
// Parse the file
while (xmlRdr.Read())
{
switch (xmlRdr.NodeType)
{
case XmlNodeType.Element:
// You may need to capture the last element to provide a context
// for any comments you come across... so copy xmlRdr.Name, etc.
break;
case XmlNodeType.Comment:
MessageBox.Show(xmlRdr.Name);
break;
case XmlNodeType.Text: //Display the text in each element.
//Console.WriteLine(reader.Value);
break;
case XmlNodeType.EndElement: //Display the end of the element.
//Console.Write("</" + reader.Name);
//Console.WriteLine(">");
break;
}
}
Thanks
try this
String xml = #"<Server ServerName=""SP-SWD-T01"">Some nodes are there</Server>";
XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);
String servername = doc.SelectSingleNode("/Server").Attributes["ServerName"].Value;
I'm using an XmlReader to iterate through some XML. Some of the XML is actually HTML and I want to get the text content from the node.
Example XML:
<?xml version="1.0" encoding="UTF-8"?>
<data>
<p>Here is some <b>data</b></p>
</data>
Example code:
using (XmlReader reader = new XmlReader(myUrl))
{
while (reader.Read())
{
if (reader.Name == "p")
{
// I want to get all the TEXT contents from the this node
myVar = reader.Value;
}
}
}
This doesn't get me all the contents. How do I get all the contents from the node in that situation?
Use ReadInnerXml:
StringReader myUrl = new StringReader(#"<?xml version=""1.0"" encoding=""UTF-8""?>
<data>
<p>Here is some <b>data</b></p>
</data>");
using (XmlReader reader = XmlReader.Create(myUrl))
{
while (reader.Read())
{
if (reader.Name == "p")
{
// I want to get all the TEXT contents from the this node
Console.WriteLine(reader.ReadInnerXml());
}
}
}
Or if you want to skip the <b> as well, you can use an aux reader for the subtree, and only read the text nodes:
StringReader myUrl = new StringReader(#"<?xml version=""1.0"" encoding=""UTF-8""?>
<data>
<p>Here is some <b>data</b></p>
</data>");
StringBuilder myVar = new StringBuilder();
using (XmlReader reader = XmlReader.Create(myUrl))
{
while (reader.Read())
{
if (reader.Name == "p")
{
XmlReader pReader = reader.ReadSubtree();
while (pReader.Read())
{
if (pReader.NodeType == XmlNodeType.Text)
{
myVar.Append(pReader.Value);
}
}
}
}
}
Console.WriteLine(myVar.ToString());
I can't upvote or comment on others' responses, so let me just say carlosfigueira hit the nail on the head, that's exactly how you read the text value of an element. his answer helped me immensely.
for the sake of exmeplification here's my code:
while (reader.Read())
{
switch (reader.NodeType)
{
case XmlNodeType.Element:
{
if (reader.Name == "CharCode")
{
switch (reader.ReadInnerXml())
{
case "EUR":
{
reader.ReadToNextSibling("Value");
label4.Text = reader.ReadInnerXml();
}
break;
case "USD":
{
reader.ReadToNextSibling("Value");
label3.Text = reader.ReadInnerXml();
}
break;
case "RUB":
{
reader.ReadToNextSibling("Value");
label5.Text = reader.ReadInnerXml();
}
break;
case "RON":
{
reader.ReadToNextSibling("Value");
label6.Text = reader.ReadInnerXml();
}
break;
}
}
}
break;
}
}
the file I'm reading can be found here: http://www.bnm.md/md/official_exchange_rates?get_xml=1&date=
(you have to add a date in DD.MM.YYYY format to it to get the .XML)
I suggest you use HtmlAgilityPack which is a mature and, stable library for doing this sort of thing. It takes care of fetching the html, converting it to xml, and allows you to select the nodes you'd like with XPATH.
In your case it would be as simple as executing
HtmlDocument doc = new HtmlWeb().Load(myUrl);
string text = doc.DocumentNode.SelectSingleNode("/data/p").InnerText;