How to modify an xml attribute's value? - c#

How can i modify the value of an attribute within an xml loaded using Loadxml()?
I'm trying to update the xml string stored in my db. For that, i used the following code:
XmlDocument doc = new XmlDocument();
doc.LoadXml(project.ProjectData);
XmlNodeList pNodes = doc.SelectNodes("project");
foreach (XmlNode pNode in pNodes)
{
XmlAttribute lPDAttribute = pNode.Attributes["lastPubDate"];
if (lPDAttribute != null)
{
string currentValue = lPDAttribute.Value;
if (string.IsNullOrEmpty(currentValue))
{
lPDAttribute.Value = project.PublishDate.ToString();
}
}
}
What should i do to save the updated attribute within my current xml? Please help.

I think you should add the below code line
project.ProjectData = doc.InnerXml

you can store doc.InnerXml as a string in your db

Related

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.

How to process JSON to remove period from field names?

As a follow up to this question I cannot figure out how to remove a period from all of my field names in JSON input.
I am converting XML to JSON and creating a BsonDocument to be inserted into a MongoDB database using the Newtonsoft library like this:
XmlDocument doc = new XmlDocument();
doc.Load(filePath);
String jsonText = JsonConvert.SerializeXmlNode(doc);
BsonDocument = MongoDB.Bson.Serialization.BsonSerializer.Deserialize<BsonDocument>(jsonText);
I can't insert this because I'll get a serialization exception since the element name contains a period. How can I process through either the JSON string or the BsonDocument to change them?
I have successfully iterated through my document recursively:
private void Print(BsonDocument document)
{
foreach (BsonElement element in document)
{
Console.WriteLine(element.Name);
if (element.Value.IsBsonDocument)
{
Print(element.Value.AsBsonDocument);
}
else if (element.Value.IsBsonArray)
{
var array = element.Value.AsBsonArray;
foreach (BsonDocument doc in array)
{
Print(doc);
}
}
}
}
However, BsonDocument.Name is not a field I can set, only get. How can I update the BsonDocument or the JSON string to remove the invalid field names?
I dont know enough about your XML/JSON structure but why dont you process the XML before you convert it into JSON and replace the ElementNames? As outlined in this ANSWER?
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(File.ReadAllText(#"{path}\xml.xml", Encoding.Default));
XmlNodeList nodeList = xmlDoc.SelectNodes("//*['.' = substring(name(), string-length(name())- string-length('.') +1)]");
foreach (XmlNode node in nodeList)
{
string newName = node.Name.Replace(".", "");
// create new (renamed) Content node
XmlNode newNode = xmlDoc.CreateElement(newName);
newNode.InnerXml = node.InnerXml;
// replace existing BatteryTest node with newly renamed Content node
node.ParentNode.InsertBefore(newNode, node);
node.ParentNode.RemoveChild(node);
}
xmlDoc.Save(#"{path}\xml.xml");

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);
}

How to iterate a xml file with XmlReader class

my xml stored in xml file which look like as below
<?xml version="1.0" encoding="utf-8"?>
<metroStyleManager>
<Style>Blue</Style>
<Theme>Dark</Theme>
<Owner>CSRAssistant.Form1, Text: CSR Assistant</Owner>
<Site>System.ComponentModel.Container+Site</Site>
<Container>System.ComponentModel.Container</Container>
</metroStyleManager>
this way i am iterating but some glitch is there
XmlReader rdr = XmlReader.Create(System.IO.Path.GetDirectoryName(System.Windows.Forms.Application.ExecutablePath) + #"\Products.xml");
while (rdr.Read())
{
if (rdr.NodeType == XmlNodeType.Element)
{
string xx1= rdr.LocalName;
string xx = rdr.Value;
}
}
it is always getting empty string xx = rdr.Value;
when element is style then value should be Blue as in the file but i am getting always empty....can u say why?
another requirement is i want to iterate always within <metroStyleManager></metroStyleManager>
can anyone help for the above two points. thanks
Blue is the value of Text node, not of Element node. You either need to add another if to get value of text nodes, or you can read inner xml of current element node:
rdr.MoveToContent();
while (rdr.Read())
{
if (rdr.NodeType == XmlNodeType.Element)
{
string name = rdr.LocalName;
string value = rdr.ReadInnerXml();
}
}
You can also use Linq to Xml to get names and values of root children:
var xdoc = XDocument.Load(path_to_xml);
var query = from e in xdoc.Root.Elements()
select new {
e.Name.LocalName,
Value = (string)e
};
You can use the XmlDocument class for this.
XmlDocument doc = new XmlDocument.Load(filename);
foreach (XmlNode node in doc.ChildNodes)
{
if (node.ElementName == "metroStyleManager")
{
foreach (XmlNode subNode in node.ChildNodes)
{
string key = subNode.LocalName; // Style, Theme, etc.
string value = subNode.Value; // Blue, Dark, etc.
}
}
else
{
...
}
}
you can user XDocument xDoc = XDocument.Load(strFilePath) to load XML file.
then you can use
foreach (XElement xeNode in xDoc.Element("metroStyleManager").Elements())
{
//Check if node exist
if (!xeNode.Elements("Style").Any()
//If yes then
xeNode.Value
}
Hope it Helps...
BTW, its from System.XML.Linq.XDocument

Update or inserting a node in an XML doc

I am a beginner to XML and XPath in C#. Here is an example of my XML doc:
<root>
<folder1>
...
<folderN>
...
<nodeMustExist>...
<nodeToBeUpdated>some value</nodeToBeUpdated>
....
</root>
What I need is to update the value of nodeToBeUdpated if the node exists or add this node after the nodeMustExist if nodeToBeUpdated is not there. The prototype of the function is something like this:
void UpdateNode(
xmlDocument xml,
string nodeMustExist,
string nodeToBeUpdte,
string newVal
)
{
/*
search for XMLNode with name = nodeToBeUpdate in xml
to XmlNodeToBeUpdated (XmlNode type?)
if (xmlNodeToBeUpdated != null)
{
xmlNodeToBeUpdated.value(?) = newVal;
}
else
{
search for nodeMustExist in xml to xmlNodeMustExist obj
if ( xmlNodeMustExist != null )
{
add xmlNodeToBeUpdated as next node
xmlNodeToBeUpdte.value = newVal;
}
}
*/
}
Maybe there are other better and simplified way to do this. Any advice?
By the way, if nodeToBeUpdated appears more than once in other places, I just want to update the first one.
This is to update all nodes in folder:
public void UpdateNodes(XmlDocument doc, string newVal)
{
XmlNodeList folderNodes = doc.SelectNodes("folder");
if (folderNodes.Count > 0)
foreach (XmlNode folderNode in folderNodes)
{
XmlNode updateNode = folderNode.SelectSingleNode("nodeToBeUpdated");
XmlNode mustExistNode = folderNode.SelectSingleNode("nodeMustExist"); ;
if (updateNode != null)
{
updateNode.InnerText = newVal;
}
else if (mustExistNode != null)
{
XmlNode node = folderNode.OwnerDocument.CreateNode(XmlNodeType.Element, "nodeToBeUpdated", null);
node.InnerText = newVal;
folderNode.AppendChild(node);
}
}
}
If you want to update a particular node, you cannot pass string nodeToBeUpdte, but you will have to pass the XmlNode of the XmlDocument.
I have omitted the passing of node names in the function since nodes names are unlikely to change and can be hardcoded. However, you can pass these to the functions and use the strings instead of hardcoded node names.
The XPath expression that selects all instances of <nodeToBeUpdated> would be this:
/root/folder[nodeMustExist]/nodeToBeUpdated
or, in a more generic form:
/root/folder[*[name() = 'nodeMustExist']]/*[name() = 'nodeToBeUpdated']
suitable for:
void UpdateNode(xmlDocument xml,
string nodeMustExist,
string nodeToBeUpdte,
string newVal)
{
string xPath = "/root/folder[*[name() = '{0}']]/*[name() = '{1}']";
xPath = String.Format(xPath, nodeMustExist, nodeToBeUpdte);
foreach (XmlNode n in xml.SelectNodes(xPath))
{
n.Value = newVal;
}
}
Have a look at the SelectSingleNode method MSDN Doc
your xpath wants to be something like "//YourNodeNameHere" ;
once you have found that node you can then traverse back up the tree to get to the 'nodeMustExist' node:
XmlNode nodeMustExistNode = yourNode.Parent["nodeMustExist];

Categories

Resources