Modify a single XML attribute in C# - c#

I've got it writing the XML doc fine, and it will look something like this
<Team>
<Character Name="Bob" Class="Mage"/>
<Character Name="Mike" Class="Knight"/>
</Team>
I'm trying to find a way to access "Class" attribute of a single character and modify it. So far, i've got it to the point where I can pinpoint a specific character, but I can't figure out how to access the 'Class' attribute and modify it for the char.
void Write(string path, string charName, string varToChange, string value){
XmlNode curNode = null;
XmlDocument doc = new XmlDocument();
doc.Load(path);
XmlElement rootDoc = doc.DocumentElement;
curNode = rootDoc;
if(curNode.HasChildNodes){
for(int i=0; i<curNode.ChildNodes.Count; i++){
if(charName == curNode.ChildNodes[i].Attributes.GetNamedItem("Name").Value){
// Code would go here
}
}
}
return;
}

Use XPATH:
XmlDocument doc = new XmlDocument();
doc.Load(path);
var nodes = doc.SelectNodes(String.Format("/Team/Character[#Name=\"{0}\"]", charName));
foreach (XmlElement n in nodes)
{
n.SetAttribute(varToChange, value);
}

Use the XmlElement.SetAttribute('attribute to modify', 'value to set it to') method
edit:
I just noticed you were using XMLNode instead of XMLElement, so in order to update the attribute you can either just cast the XmlNode to an XmlElement like so
XmlElement el = (XmlElement)curNode;
el.SetAttribute("Class", "Value");
Otherwise you can create an attribute and then append it in order to update the attribute:
XmlAttribute attrib =
curNode.OwnerDocument.CreateAttribute("Class");
attrib.Value = "Value";
curNode.Attributes.Append(attrib);
Hope this helps

Related

Insert a string in a particular position into an other string

I am work on some innerxml of an XML document.
I have to concat several parts.
I have this:
<TRANFSERT><GOOD></GOOD></TRANSFERT>
I want to insert another part, <GOOD></GOOD>, before </TRANSFERT>.
I tried this:
int pos = xmldoc.indexOf("</GOOD>");
StringBuilder sb = new StringBuilder(xmlFinal);
sb.Append(xmlModifiee,pos,xmlModifiee.length);
xmlFinal = sb.ToString();
But it doesn't work.
How can I add a small part of XML in other XML?
You shouldn't interact with XML like with ordinary string.
Use provided System.Xml.XmlDocument or System.Xml.Linq.XDocument classes:
Ordinary XmlDocument single node selection and appending new element to it:
XmlDocument xmlDocument = new XmlDocument();
xmlDocument.Load("YourFile.xml");
XmlNode goodNode = xmlDocument.SelectSingleNode("TRANSFERT/GOOD");
XmlNode nodeToInsert = xmlDocument.CreateElement("INSERTEDNODE");
goodNode.AppendChild(nodeToInsert);
Ordinary XmlDocument iterating by nodes to find necessary (be aware for many-childed nodes) and add new child node to it:
XmlDocument xmlDocument = new XmlDocument();
xmlDocument.Load("YourFile.xml");
foreach (XmlNode rootNode in xmlDocument.ChildNodes)
{
if (rootNode.Name == "TRANSFERT")
{
foreach (XmlNode childNode in rootNode.ChildNodes)
{
if (childNode.Name == "GOOD")
{
XmlNode nodeToInsert = xmlDocument.CreateElement("INSERTEDNODE");
childNode.AppendChild(nodeToInsert);
}
}
}
}
Linq to XML variant:
XDocument xDoc = XDocument.Load("YourFIle.xml");
XElement rootElement = xDoc.Element("TRANSFERT");
XElement goodElement = rootElement.Element("GOOD");
goodElement.Add(new XElement("INSERTEDNODE"));
Simplified Linq to XML variant:
XDocument.Load("YourFIle.xml").Element("TRANSFERT").Element("GOOD").Add(new XElement("INSERTEDNODE"));
EDITED: answering the question, example was rewrited from changing InnerText values to Append/Add new child element to GOOD node.
StringBuilder.Append can only be used to add something to the end of the string. To add something inside the string, use StringBuilder.Insert like this:
sb.Insert(pos, xmlModifiee);

how to get(read) data from xmldocument in windows phone, c#

I'm getting data from a web service in my phone application and get the response to xmldocument like below.
XmlDocument XmlDoc = new XmlDocument();
XmlDoc.LoadXml(newx2);
Ther result of XmlDoc is like below.now I want to get the values from this.
<root>
<itinerary>
<FareIndex>0</FareIndex>
<AdultBaseFare>4719</AdultBaseFare>
<AdultTax>566.1</AdultTax>
<ChildBaseFare>0</ChildBaseFare>
<ChildTax>0</ChildTax>
<InfantBaseFare>0</InfantBaseFare>
<InfantTax>0</InfantTax>
<Adult>1</Adult>
<Child>0</Child>
<Infant>0</Infant>
<TotalFare>5285.1</TotalFare>
<Airline>AI</Airline>
<AirlineName>Air India</AirlineName>
<FliCount>4</FliCount>
<Seats>9</Seats>
<MajorCabin>Y</MajorCabin>
<InfoVia>P</InfoVia>
<sectors xmlns:json="http://james.newtonking.com/projects/json">
</itinerary>
</root>
I tried with this.
XmlNodeList xnList = XmlDoc.SelectNodes("/root[#*]");
but it gives null result. the count is 0. how can I read the data from this.hope your help with this.thanx.
You can use System.Xml.Linq.XElement to parse an xml:
XElement xRoot = XElement.Parse(xmlText);
XElement xItinerary = xRoot.Elements().First();
// or xItinerary = xRoot.Element("itinerary");
foreach (XElement node in xItinerary.Elements())
{
// Read node here: node.Name, node.Value and node.Attributes()
}
If you want to use XmlDocument you can do like this:
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(xmlText);
XmlNode itinerary = xmlDoc.FirstChild;
foreach (XmlNode node in itinerary.ChildNodes)
{
string name = node.Name;
string value = node.Value;
// you can also read node.Attributes
}
You can get the value of a particular element like,
var fareIndex = XmlDoc.SelectSingleNode("/root/itinerary/FareIndex").InnerText;
If you want to get the list of all elements that come under root/itinerary -
XmlNodeList xnList = XmlDoc.SelectNodes("/root/itinerary/*");
This link might help you.

XML - Write a single node

I got this function for simply get the inner text of my xml:
XmlDocument document = new XmlDocument();
document.Load("game.xml");
string content = document.SelectSingleNode("Game/Client-Version").InnerText;
(this is the xml file (due to complications with stackoverflow posted on pastebin)): http://pastebin.com/EEeFAJpC
And now I am exactly looking for the function above, just to write. Like
document.WriteSingleNode("Game/Client-Version", "texttowrite");
I did not find anything helping me out.
This should work
XmlElement x = document.SelectSingleNode("Game/Client-Version") as XmlElement;
x.InnerText = "texttowrite";
Create your own extension method:
public void WriteSingleNode(this XmlDocument document, string NodeName, string InnerText)
{
// Create a new element node.
XmlNode newElem = document.CreateNode("element", "pages", "");
newElem.InnerText = InnerText;
Console.WriteLine("Add the new element to the document...");
document.DocumentElement.AppendChild(newElem);
Console.WriteLine("Display the modified XML document...");
Console.WriteLine(document.OuterXml);
}

Adding info to a xml file

I have a XML file which contains about 850 XML nodes. Like this:
<NameValueItem>
<Text>Test</Text>
<Code>Test</Code>
</NameValueItem>
........ 849 more
And I want to add a new Childnode inside each and every Node. So I end up like this:
<NameValueItem>
<Text>Test</Text>
<Code>Test</Code>
<Description>TestDescription</Description>
</NameValueItem>
........ 849 more
I've tried the following:
XmlDocument doc = new XmlDocument();
doc.Load(xmlPath);
XmlNodeList nodes = doc.GetElementsByTagName("NameValueItem");
Which gives me all of the nodes, but from here am stuck(guess I need to iterate over all of the nodes and append to each and every) Any examples?
You need something along the lines of this example below. On each of your nodes, you need to create a new element to add to it. I assume you will be getting different values for the InnerText property, but I just used your example.
foreach (var rootNode in nodes)
{
XmlElement element = doc.CreateElement("Description");
element.InnerText = "TestDescription";
root.AppendChild(element);
}
You should just be able to use a foreach loop over your XmlNodeList and insert the node into each XmlNode:
foreach(XmlNode node in nodes)
{
node.AppendChild(new XmlNode()
{
Name = "Description",
Value = [value to insert]
});
}
This can also be done with XDocument using LINQ to XML as such:
XDocument doc = XDocument.Load(xmlDoc);
var updated = doc.Elements("NameValueItem").Select(n => n.Add(new XElement() { Name = "Description", Value = [newvalue]}));
doc.ReplaceWith(updated);
If you don't want to parse XML using proper classes (i.e. XDocument), you can use Regex to find a place to insert your tag and insert it:
string s = #"<NameValueItem>
<Text>Test</Text>
<Code>Test</Code>
</NameValueItem>";
string newTag = "<Description>TestDescription</Description>";
string result = Regex.Replace(s, #"(?<=</Code>)", Environment.NewLine + newTag);
but the best solution is Linq2XML (it's much better, than simple XmlDocument, that is deprecated at now).
string s = #"<root>
<NameValueItem>
<Text>Test</Text>
<Code>Test</Code>
</NameValueItem>
<NameValueItem>
<Text>Test2</Text>
<Code>Test2</Code>
</NameValueItem>
</root>";
var doc = XDocument.Load(new StringReader(s));
var elms = doc.Descendants("NameValueItem");
foreach (var element in elms)
{
element.Add(new XElement("Description", "TestDescription"));
}
var text = new StringWriter();
doc.Save(text);
Console.WriteLine(text);

XML - how to use namespace prefixes

I have this XML at http://localhost/file.xml:
<?xml version="1.0" encoding="utf-8"?>
<val:Root xmlns:val="http://www.hw-group.com/XMLSchema/ste/values.xsd">
<Agent>
<Version>2.0.3</Version>
<XmlVer>1.01</XmlVer>
<DeviceName>HWg-STE</DeviceName>
<Model>33</Model>
<vendor_id>0</vendor_id>
<MAC>00:0A:DA:01:DA:DA</MAC>
<IP>192.168.1.1</IP>
<MASK>255.255.255.0</MASK>
<sys_name>HWg-STE</sys_name>
<sys_location/>
<sys_contact>
HWg-STE:For more information try http://www.hw-group.com
</sys_contact>
</Agent>
<SenSet>
<Entry>
<ID>215</ID>
<Name>Home</Name>
<Units>C</Units>
<Value>27.7</Value>
<Min>10.0</Min>
<Max>40.0</Max>
<Hyst>0.0</Hyst>
<EmailSMS>1</EmailSMS>
<State>1</State>
</Entry>
</SenSet>
</val:Root>
I am trying to read this from my c# code:
static void Main(string[] args)
{
var xmlDoc = new XmlDocument();
xmlDoc.Load("http://localhost/file.xml");
XmlElement root = xmlDoc.DocumentElement;
// Create an XmlNamespaceManager to resolve the default namespace.
XmlNamespaceManager nsmgr = new XmlNamespaceManager(xmlDoc.NameTable);
nsmgr.AddNamespace("val", "http://www.hw-group.com/XMLSchema/ste/values.xsd");
XmlNodeList nodes = root.SelectNodes("/val:SenSet/val:Entry");
foreach (XmlNode node in nodes)
{
string name = node["Name"].InnerText;
string value = node["Value"].InnerText;
Console.Write("name\t{0}\value\t{1}", name, value);
}
Console.ReadKey();
}
}
Problem is that the node is empty. I understand this is a common newbie problem when reading XML, still not able to solve what I am doing wrong, probably something with the Namespace "val" ?
You need to pass the namespace manager into the SelectNodes()
method.
Edit: corrected code
XmlNodeList nodes = root.SelectNodes("/val:Root/SenSet/Entry", nsmgr);
Just change you Xpath to:
XmlNodeList nodes1 = root.SelectNodes("/val:Root/SenSet/Entry",nsmgr);
Or:
XmlNodeList nodes = root.SelectNodes("SenSet/Entry");
Your xpath query string should be:
XmlNodeList nodes = root.SelectNodes("/val:Root/SenSet/Entry", nsmgr);
or more concisely,
XmlNodeList nodes = root.SelectNodes("//SenSet/Entry", nsmgr);

Categories

Resources