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);
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 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;
I have xml file like this test.xml:
<?xml version="1.0" encoding="utf-8" ?>
<Message>
<Item Name ="msg1" Status ="false"/>
<Item Name="msg2" Status="false"/>
</Message>
System.Xml.XmlTextReader textReader = new System.Xml.XmlTextReader(test.xml);
System.Xml.XmlDocument xdoc = new System.Xml.XmlDocument();
xdoc.Load(test.xml);
var testreader = xdoc.DocumentElement.ChildNodes;
string name = string.Empty;
string value = string.Empty;
if (message.MsgType == 10005)
{
value = "true";
}
else if (message.MsgType == 10002)
{
value = "false";
}
foreach (var mychild in testreader)
{
var childatt = ((System.Xml.XmlElement)mychild);
name = childatt.Attributes["Name"].Value;
value = childatt.Attributes["Status"].Value;
}
What I have to do to following thing:
I have to save updated value in xml file with xmltestReader and xmldocument
I'm getting request from third client about messageID so I have to check it's exist in xml file or not (e.g get request for msg1 so I have to match it xml file it's there or not).
hope I'm clear with my question.
//Get Message
//txtsearch text u have to pass message Id
var xmlFilePath = Server.MapPath("Test.xml");
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(xmlFilePath);
XmlNodeList nodeList = xmlDoc.DocumentElement.SelectNodes("/TableMessage/Message");
string msgID = "",msgname="";
foreach (XmlNode node in nodeList)
{
if (node.SelectSingleNode("Message_Details").InnerText == "True" && node.SelectSingleNode("Message_id").InnerText==txtsearchtext.Text)
{
msgID = node.SelectSingleNode("Message_id").InnerText;
msgname = node.SelectSingleNode("Message_name").InnerText;
}
}
//store Updated Xml in ur project xml
//get the information from end user and pass the value to correspoding fields
XmlDocument xmlEmloyeeDoc = new XmlDocument();
xmlEmloyeeDoc.Load(Server.MapPath("~/Test.xml"));
XmlElement ParentElement = xmlEmloyeeDoc.CreateElement("Message");
XmlElement ID = xmlEmloyeeDoc.CreateElement("Message_id");
ID.InnerText = "6";
XmlElement message = xmlEmloyeeDoc.CreateElement("Message_name");
message.InnerText = "Message6";
XmlElement Details = xmlEmloyeeDoc.CreateElement("Message_Details");
Details.InnerText = "True";
ParentElement.AppendChild(ID);
ParentElement.AppendChild(message);
ParentElement.AppendChild(Details);
xmlEmloyeeDoc.DocumentElement.AppendChild(ParentElement);
xmlEmloyeeDoc.Save(Server.MapPath("~/Test.xml"));
I hope that code will help u
you will customize ur xml file like this
<?xml version="1.0" encoding="utf-8"?>
<TableMessage>
<Message>
<Message_id>Message1</Message_id>
<Message_name>Message1</Message_name>
<Message_Details>True</Message_Details>
</Message>
<Message>
<Message_id>Message2</Message_id>
<Message_name>Message2</Message_name>
<Message_Details>True</Message_Details>
</Message>
<Message>
<Message_id>Message3</Message_id>
<Message_name>Message3</Message_name>
<Message_Details>False</Message_Details>
</Message>
</TableMessage>
I want to modify XML data given below:
<?xml version="1.0" encoding="utf-8"?>
<allitems>
<item ID="17997" quantity="three">
<available>Y</available>
<last_modified_price>300</last_modified_price>
<edition>2008<edition>
<item>
<item ID="18039" quantity="two">
<available>Y</available>
<last_modified_price>250</last_modified_price>
<edition>2010<edition>
<item>
</allitems>
all elements value should be modified as per set in runtime....
For this I used following code but data is not modified..please help me in getting solution.
XmlDocument modifydoc = new XmlDocument();
modifydoc.Load(#"E:\XMLapp\XMLstorageWEB\patrick\XMLFile1.xml");
var root = modifydoc.GetElementsByTagName("allitems")[0];
var oldelem = root.SelectSingleNode("item[#ID =" + txt_id.Text + "]");
var newelem = modifydoc.CreateElement("item");
root.ReplaceChild(newelem, oldelem);
while (oldelem.ChildNodes.Count != 0)
{
XmlElement available= modifydoc.CreateElement("available");
available.InnerText = ddl_available.SelectedItem.Text;
XmlElement last_modified_price= modifydoc.CreateElement("last_modified_price");
last_modified_price.InnerText = ddl_last_modified_price.SelectedItem.Text;
XmlElement edition= modifydoc.CreateElement("edition");
edition.InnerText = ddl_edition.SelectedItem.Text;
newelem.AppendChild(available);
newelem.AppendChild(last_modified_price);
newelem.AppendChild(edition);
modifydoc.DocumentElement.AppendChild(newelem);
}
while (oldelem.Attributes.Count != 0)
{
newelem.Attributes.Append(oldelem.Attributes[0]);
}
modifydoc.Save(#"E:\XMLapp\XMLstorageWEB\patrick\XMLFile1.xml");
please give me solution..
Not the cleanest way, to add and remove a XmlNode, but just fixing your code I think this is what you want
var txt_id = "17997";
XmlDocument modifydoc = new XmlDocument();
modifydoc.Load(#"c:\temp\so\1.xml");
var root = modifydoc.GetElementsByTagName("allitems")[0];
var oldelem = root.SelectSingleNode("item[#ID =" + txt_id + "]");
var newelem = modifydoc.CreateElement("item");
root.ReplaceChild(newelem, oldelem);
XmlElement available= modifydoc.CreateElement("available");
available.InnerText = "CambiameInnerText";
XmlElement last_modified_price= modifydoc.CreateElement("last_modified_price");
last_modified_price.InnerText = "LastModifed";
XmlElement edition= modifydoc.CreateElement("edition");
edition.InnerText = "SelectedItem";
newelem.AppendChild(available);
newelem.AppendChild(last_modified_price);
newelem.AppendChild(edition);
modifydoc.DocumentElement.AppendChild(newelem);
foreach (XmlAttribute attribute in oldelem.Attributes)
{
newelem.SetAttribute(attribute.Name, attribute.Value);
}
and your xml is not correct, at least the example
<?xml version="1.0" encoding="utf-8"?>
<allitems>
<item ID="17997" quantity="three">
<available>Y</available>
<last_modified_price>300</last_modified_price>
<edition>2008</edition>
</item>
<item ID="18039" quantity="two">
<available>Y</available>
<last_modified_price>250</last_modified_price>
<edition>2010</edition>
</item>
</allitems>
Here is the small and easy example , i use for change the connectionString value in my [web.config]. I hope it's can help you. So easy to adapt for your code ;-)
System.Xml.XmlDocument myXmlDocument = new System.Xml.XmlDocument();
myXmlDocument.Load("myFullPathWebConfig.xml");
foreach (System.Xml.XmlNode node in myXmlDocument["configuration"]["connectionStrings"])
{
if (node.Name == "add")
{
if (node.Attributes.GetNamedItem("name").Value == "SCI2ConnectionString")
{
node.Attributes.GetNamedItem("connectionString").Value = connectionString;
}
}
}
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;