How do I insert inner text into empty xml element? - c#

I have an xmldocument that i'm loading xml in to.
The xml looks like this:
<Table1>
<buyer_id>0</buyer_id>
<buyername>CompanyA</buyername>
<address1>123 Simpsons Dr.</address1>
<address2/>
<city>Springfield</city>
<state>ST</state>
<postalcode>12345</postalcode>
<eaddress/>
<phone/>
<fax/>
</Table1>
I'm looping through looking at each CompanyA entry and setting innertext accordingly. I'm using the following code to insert inner text into elements that meet the criteria:
XmlDocument dom = new XmlDocument();
dom.LoadXml(xmlString);
XmlNodeList elemList = dom.GetElementByTagName("Table1");
for(int i = 0; i < elemList.Count; i++)
{
if(dom.GetElementsByTagName("buyername").Item(i).InnerText.Contains("CompanyA")
{
dom.GetElementsByTagName("address1").Item(i).InnerText = "SomeInfo";
}
}
Using the above code, the value of address1(123 Simpsons Dr.) would be replaced by "SomeInfo". I would like to instead insert "SomeInfo" into the address2 element but when I try using:
dom.GetElementsByTagName("address2").Item(i).InnerText = "SomeInfo";
I get an error. I'm able to insert innertext into any element that already has a value but I cannot when the element is empty (such as <address2/>). Thoughts?

Use LINQ2XML.It's a complete replacement to other XML api's like the dirty old idiot XmlDocument
XElement doc=XElement.Load("yourXml.xml");
foreach(var elm in doc.Descendants("Table1"))
{
if(elm.Element("buyername").Value=="CompanyA")
elm.Element("address2").Value="SomeInfo";
}
doc.Save("yourXml.xml");

Check if the address2 xml tag is empty.
If yes , go to its parent and remove the tag then again add the same tag with value.
If no , assign the inner text to address2.
let me know if you need the code.

Use the SetElementValue method in LINQ to XML:
XDocument doc = XDocument.Load(FilePath); //replace with xml file path
IEnumerable<XElement> buyersList = doc.Descendants("Table1"); //get the table node.
var ele = (from buyer in buyersList
where buyer.Element("buyername").Value == "CompanyA"
select buyer).SingleOrDefault();
ele.SetElementValue("address1", "SomeInfo");
ele.SetElementValue("address2", "SomeInfo");
doc.Save(FilePath);
DEMO: http://ideone.com/Cf7YI

Related

How do I read xml in C#? [duplicate]

How can I read an XML attribute using C#'s XmlDocument?
I have an XML file which looks somewhat like this:
<?xml version="1.0" encoding="utf-8" ?>
<MyConfiguration xmlns="http://tempuri.org/myOwnSchema.xsd" SuperNumber="1" SuperString="whipcream">
<Other stuff />
</MyConfiguration>
How would I read the XML attributes SuperNumber and SuperString?
Currently I'm using XmlDocument, and I get the values in between using XmlDocument's GetElementsByTagName() and that works really well. I just can't figure out how to get the attributes?
XmlNodeList elemList = doc.GetElementsByTagName(...);
for (int i = 0; i < elemList.Count; i++)
{
string attrVal = elemList[i].Attributes["SuperString"].Value;
}
You should look into XPath. Once you start using it, you'll find its a lot more efficient and easier to code than iterating through lists. It also lets you directly get the things you want.
Then the code would be something similar to
string attrVal = doc.SelectSingleNode("/MyConfiguration/#SuperNumber").Value;
Note that XPath 3.0 became a W3C Recommendation on April 8, 2014.
You can migrate to XDocument instead of XmlDocument and then use Linq if you prefer that syntax. Something like:
var q = (from myConfig in xDoc.Elements("MyConfiguration")
select myConfig.Attribute("SuperString").Value)
.First();
I have an Xml File books.xml
<ParameterDBConfig>
<ID Definition="1" />
</ParameterDBConfig>
Program:
XmlDocument doc = new XmlDocument();
doc.Load("D:/siva/books.xml");
XmlNodeList elemList = doc.GetElementsByTagName("ID");
for (int i = 0; i < elemList.Count; i++)
{
string attrVal = elemList[i].Attributes["Definition"].Value;
}
Now, attrVal has the value of ID.
XmlDocument.Attributes perhaps? (Which has a method GetNamedItem that will presumably do what you want, although I've always just iterated the attribute collection)
Assuming your example document is in the string variable doc
> XDocument.Parse(doc).Root.Attribute("SuperNumber")
1
If your XML contains namespaces, then you can do the following in order to obtain the value of an attribute:
var xmlDoc = new XmlDocument();
// content is your XML as string
xmlDoc.LoadXml(content);
XmlNamespaceManager nsmgr = new XmlNamespaceManager(new NameTable());
// make sure the namespace identifier, URN in this case, matches what you have in your XML
nsmgr.AddNamespace("ns", "urn:oasis:names:tc:SAML:2.0:protocol");
// get the value of Destination attribute from within the Response node with a prefix who's identifier is "urn:oasis:names:tc:SAML:2.0:protocol" using XPath
var str = xmlDoc.SelectSingleNode("/ns:Response/#Destination", nsmgr);
if (str != null)
{
Console.WriteLine(str.Value);
}
More on XML namespaces here and here.

How to get InnerText and InnerXml of a Node from XmlDocument?

For example, I have this xml string:
<?xml version="1.0" encoding="utf-8"?>
<data>
<text>How to get <bold>all</bold> this string's content?</text>
</data>
I want to get all these elements in an array of objects (for each object I have a class), without loosing their structure:
[1] (TextClass; where bold = false) How to get
[2] (TextClass; where bold = true) all
[3] (TextClass; where bold = false) this string's content?
All I'm getting using XmlDocument and XmlNode classes right now is InnerText Or InnerXml separately.
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load("example.xml");
foreach (XmlNode child in xmlDoc.DocumentElement.ChildNodes)
{
string chName = child.Name; // text
string text = child.InnerText; // How to get all this string's content?
string xml = child.InnerXml; // How to get <bold>all</bold>this string's content?
}
Is it possible?
For this kind of work I think it is easier to use the LINQ to XML.
In your example something like the following could work (depending on exactly what you want to achieve):
XDocument doc = XDocument.Parse(xml);
var textClasses = from n in doc.Descendants("text").DescendantNodes()
where n.NodeType == XmlNodeType.Text
select new { text = ((XText)n).Value, bold = n.Parent?.Name == "bold" };
And a .net fiddle so you can quickly see the result.

Xdocument, get each element(s) value

I have xml as follows:
<Reports>
<report>
<name>By Book</name>
<report_type>book</report_type>
<Object>Count Change</Object>
<Slicers detail="detail">
<Namespace>EOD</Namespace>
<BookNode>HighLevel</BookNode>
<DateFrom>T-2</DateFrom>
<DateTo>T-1</DateTo>
<System>NewSystem</System>
</Slicers>
</report>
</Reports>
I simply want to loop through the value of each element of the Xdocument (pref would be any element under Slicers) but to start with just all elements.
When I run the following:
var slicers = from c in config.Elements("Reports")
select c.Value ;
foreach (var xe in slicers)
{
Console.WriteLine(xe);
}
The output is a single line concatenating all the values together.
"By BookbookCount ChangeEODHighLevelT-2T-1NewSystem"
I want to loop through them one at a time, 'By Book' first, run some code then book etc etc.
I am sure this is simple, but cant get round it. I have tried foreach(Xelement in query) but same resulst
i would do it something like this;
XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);
//load in your xml here
XmlNodeList xnList = doc.SelectNodes("nodeYou'reLookingFor");
//for getting just the splicers you could do "Reports/report/Slicers"
foreach (XmlNode node in xnList)
string namespace = node["Namespace"].InnerText;
//go through all your nodes here
you're creating a xmldoc, loading your xml into it, creating a list which holds each node in the list (at a specified Xpath), and then looping through each. in the loop you can do whatever you want by referencing
node["nodenamehere"].InnerText

Get xml node using c#

I have a request that returns a large xml file. I have the file in a XmlDocument type in my application. From that Doc how can I read an element like this:
<gphoto:videostatus>final</gphoto:videostatus>
I would like to pull that value final from that element. Also If i have multiple elements as well, can I pull that into a list? thanks for any advice.
If you already have an XmlDocument then you can use the function GetElementsByTagName() to create an XmlNodeList that can be accessed similar to an array.
http://msdn.microsoft.com/en-us/library/dc0c9ekk.aspx
//Create the XmlDocument.
XmlDocument doc = new XmlDocument();
doc.Load("books.xml");
//Display all the book titles.
XmlNodeList elemList = doc.GetElementsByTagName("title");
for (int i=0; i < elemList.Count; i++)
{
Console.WriteLine(elemList[i].InnerXml);
}
You can select nodes using XPath and SelectSingleNode SelectNodes. Look at http://www.codeproject.com/Articles/9494/Manipulate-XML-data-with-XPath-and-XmlDocument-C for examples. Then you can use for example InnerText to get final. Maybe you need to work with namespaces (gphoto). The //videostatus would select all videostatus elements
You can try using LINQ
XNamespace ns = XNamespace.Get(""); //use the xmnls namespace here
XElement element = XElement.Load(""); // xml file path
var result = element.Descendants(ns + "videostatus")
.Select(o =>o.Value).ToList();
foreach(var values in value)
{
}
Thanks
Deepu

XPath and attributes

I'm trying to traverse an XML document and select certain node attributes. The XML is dynamically generated.
<?xml version="1.0" encoding="ISO-8859-1"?>
<streams>
<stream>
<title>+23 (Panama)</title>
<info resolution="768x420" bitrate="1000kbps"/> ----- Need These
<swfUrl>http://www.freeetv.com/script/mediaplayer/player.swf</swfUrl>
<link>rtmp://200.75.216.156/live/</link>
<pageUrl>http://www.freeetv.com/</pageUrl>
<playpath>livestream</playpath>
<language>Music</language>
<advanced></advanced>
</stream>
</streams>
The code that I'm trying to use with zero luck and Visual Studio saying "No you're wrong. Try 600 more times" is
xDoc.Load("http://127.0.0.1/www/xml.php");
XmlNodeList nodes = xDoc.SelectNodes("/streams/stream");
foreach (XmlNode xn in nodes)
{
ListViewItem lvi = listView1.Items.Add(xn["title"].InnerText);
lvi.SubItems.Add(xn["swfUrl"].InnerText);
lvi.SubItems.Add(xn["link"].InnerText);
lvi.SubItems.Add(xn["pageUrl"].InnerText);
lvi.SubItems.Add(xn["playpath"].InnerText);
lvi.SubItems.Add(xn["language"].InnerText);
lvi.SubItems.Add(xn["advanced"].InnerText);
lvi.SubItems.Add(xn["//info/#resolution"].Value);
}
Please tell me oh wise ones what am I doing wrong?
If you want to select node's attribute using XPath you should use SelectSingleNode method, e.g.:
xn.SelectSingleNode("info/#resolution").Value
To select resolution attribute of your last node you need to use:
xn["info"].Attributes["resolution"].Value
Alternatively, you can try LINQ to XML for the same results (I find its API easier to use):
var doc = XDocument.Parse("http://127.0.0.1/www/xml.php");
foreach (var d in doc.Descendants("stream"))
{
ListViewItem lvi = listView1.Items.Add(d.Element("title").Value);
lvi.SubItems.Add(d.Element("swfUrl").Value);
// ...
vi.SubItems.Add(d.Element("info").Attribute("resolution").Value);
}
Here is an example of LINQ to XML to extract attributes from the entire document of a particular attribute name OR list of attribute names.
var xml = XElement.Parse("http://127.0.0.1/www/xml.php");
// find all attributes of a given name
var attributes = xml
.Descendants()
.Attributes("AttributeName")
// find all attributes of multiple names
var attributes = xml
.Descendants()
.Attributes()
.Where(a => ListOfAttribNames.Contains(a.Name.LocalName))
Replace:
lvi.SubItems.Add(xn["//info/#resolution"].Value);
with:
lvi.SubItems.Add(xn.SelectSingleNode("info/#resolution").Value);

Categories