Load XML from DB using C# - c#

I want to retrieve the XML data from db and bound it to the DropDownList.
XML data in the db field is follows:
<Root>
<ClientName>Jim</ClientName>
<ClientName>John</ClientName>
<ClientName>Andrew</ClientName>
</Root>
i retrieved the xml data from db field. but, i got next error:
Data at the root level is invalid. Line 1, position 1
The following code used to retrieve the xml data from db field. do you have any idea about this problem?
var list = from drp in zephyrEntities.UserDefinedFields
where drp.UDF_ID == udfid
select drp.LIST_VALUES; // xml field in the db
XmlDocument doc = new XmlDocument();
XElement xelement = new XElement("UserDefinedList", list);
string str = String.Concat(xelement.Nodes());
doc.LoadXML(str);
XmlNodeList childNodes = doc.GetElementsByTagName("ClientName");
if (childNodes != null)
{
for (int i = 0; i < childNodes.Count; i++)
{
XmlNode valueNode = childNodes[i].SelectSingleNode("text()");
}
}

It is not clear why you store list of entities as one value. Try to normalize your DB model.

Related

Writing/Overwriting to specific XML file from ASP.NET code behind

I have a XML world map which basically takes two inputs (its a XML file with corresponding CSS files and stuff): the country input and country address. So when I manually enter the data into the XML file (Country name and country address) the country on the map changes its color and on hovering over that country I can see what I've entered.
I have a list of all countries in my DB. So I was thinking of there is any way for me to write in all those countries from my DB into the XML file. I was thinking of something like this:
for(int i=0; i<list.count;i++)
{
list[i].CounryName = //write it into the XML file;
list[i].CountryUserAddress = //Write it into the XML file;
}
So the idea is to when the for loop goes on and on, every country is written in into the XML file. I don't have any significant experience working with XML files in ASP.NET and I'm stuck on dry land here. All this should be done via code behind. Can someone help me out with this, or at least point me into the right direction?
Thanks heaps!
P.S. I've forgot to mention that I should be actually overwriting the already existing XML file, not creating a new one...
Here's an example of how you could do this with the data you provided:
public string EditDoc()
{
string filename = "Path/MyFileName.xml";
List<string> list = new List<string>();
if (File.Exists(filename)) //we have the file, so update it
{
XmlDocument myDoc = new XmlDocument(); //create a document object
myDoc.Load(filename); //load existing info
XmlNode root = myDoc.DocumentElement; //the root node ("Country")
XmlNode nodeToUpdate = root.SelectSingleNode("CountryName"); //select the node to update
nodeToUpdate.Value = "new info"; //give it a new value
myDoc.Save(filename); //save the document
}
else //didn't find the file
{
XmlDocument myDoc = new XmlDocument(); //create a new document
XmlNode countryList = myDoc.CreateElement("CountryList");
myDoc.AppendChild(countryList);
for (int i = 0; i < list.Count; i++)
{
XmlNode country = myDoc.CreateElement("Country"); //create the parent "Country" element
myDoc.AppendChild(countryList); //append to the list
XmlNode countryName = myDoc.CreateElement("CountryName"); //create element for "CountryName"
countryName.AppendChild(myDoc.CreateTextNode(list[i].CountryName)); //add data from list index
country.AppendChild(countryName); //append this as a child to "Country"
XmlNode countryUserAddress = myDoc.CreateElement("CountryUserAddress"); //create element for "CountryUserAddress"
countryUserAddress.AppendChild(myDoc.CreateTextNode(list[i].CountryUserAddress)); //add data from list index
country.AppendChild(countryUserAddress); //append as a child to "Country"
}
myDoc.Save(filename); //save the document
}
}
The general idea is to traverse the document's tree and select that value to update. There may be a better way to do this, but this is the way I'm familiar with. Similarly, you can create an xml document in the same manner.
The subject matter is different, but this helped me tremendously in understanding reading/writing XML data: this link
EDIT: I updated the code slightly to make the parent element "CountryList" and append each "Country" in the DB to that. The document will end up coming out something like:
<CountryList>
<Country>
<CountryName>Blah</CountryName>
<CountryUserAddress>Blah</CountryUserAddress>
</Country>
<Country>
<CountryName>Blah</CountryName>
<CountryUserAddress>Blah</CountryUserAddress>
</Country>
</CountryList>

Read XML with schema without xsd file

I received a complex XML file this week and it is schema based, but i didn't received any xsd file and i need to read each node of this one.
XML sample bellow:
<xc:XmlTest xmlns:xc="XmlTest" xmlns:mp="bs.TestParameters" xmlns:rt="bs.TestParameters.Parameter1" xmlns:rtcu="bs.TestParameters.Parameter1.Var">
<xc:XmlTestArea xc:value="TestParameters">
<mp:Name xc:Value="raddesso" xmlns:mp="bs.TestParameters">
<mp:Date xc:Value="20130215">
<rt:RunTest xmlns:rt="bs.TestParameters.Parameter1">
<rtcu:Var xmlns:rtcu="bs.TestParameters.Parameter1.Var">
<mp:FinalValue>1234</mp:FinalValue>
</rtcu:Var>
</rt:RunTest>
</mp:Date>
<mp:Date xc:Value="20130216">
<rt:RunTest xmlns:rt="bs.TestParameters.Parameter1">
<rtcu:Var xmlns:rtcu="bs.TestParameters.Parameter1.Var">
<mp:FinalValue>23234</mp:FinalValue>
</rtcu:Var>
</rt:RunTest>
</mp:Date>
</mp:Name>
</xc:XmlTestArea>
</xc:XmlTest>
This is only a sample of the true file, using fake data.
Is there any way to do a foreach on this nodes to find the FinalValue from each date?
You don't need a schema to read a file. The schema is only used to validate the file (to check integrity). But this step is optional.
To read the XML file. I suggest to use Linq-to-XML.
const string mpNamespace = "bs.TestParameters";
XDocument xDocument = XDocument.Load("C:/Path to the file.xml");
List<string> finalValues = (from dateNode in xDocument.Descendants(XName.Get("Date", mpNamespace)) // Gets all Date nodes in the document
from finalValueNode in dateNode.Descendants(XName.Get("FinalValue", mpNamespace)) // Gets all FinalValue nodes in the Date nodes
select finalValueNode.Value // Gets the value of each FinalValue node
).ToList();
Update
To return the Date and the FinalValue you can use anonymous types:
const string mpNamespace = "bs.TestParameters";
const string xcNamespace = "XmlTest";
XDocument xDocument = XDocument.Load("C:/Path to the file.xml");
var finalValues = (from dateNode in xDocument.Descendants(XName.Get("Date", mpNamespace)) // Gets all Date nodes in the document
from finalValueNode in dateNode.Descendants(XName.Get("FinalValue", mpNamespace)) // Gets all FinalValue nodes in the Date nodes
select new // Creates an instance of an anonymous type with Date and FinalValue
{
Date = dateNode.Attribute(XName.Get("Value", xcNamespace)).Value,
FinalValue = finalValueNode.Value // Gets the value of each FinalValue node
}
).ToList();
XmlDocument doc = new XmlDocument();
doc.Load("path to xml file");
XmlNodeList finalValues = doc.GetElementByTagName("FinalValue");
finalValues will be a list of node that has the tag name "FinalValue", you can then read the inner text and story in a list.
List<string> values = new List<string>();
foreach(XmlNode node in finalValues)
values.Add(node.InnerText);

A better way to handle XML updation

I have a DataGridView control where some values are popluted.
And also I have an xml file. The user can change the value in the Warning Column of DataGridView.And that needs to be saved in the xml file.
The below program just does the job
XDocument xdoc = XDocument.Load(filePath);
//match the record
foreach (var rule in xdoc.Descendants("Rule"))
{
foreach (var row in dgRulesMaster.Rows.Cast<DataGridViewRow>())
{
if (rule.Attribute("id").Value == row.Cells[0].Value.ToString())
{
rule.Attribute("action").Value = row.Cells[3].Value.ToString();
}
}
}
//save the record
xdoc.Save(filePath);
Matching the grid values with the XML document and for the matched values, updating the needed XML attribute.
Is there a better way to code this?
Thanks
You could do something like this:
var rules = dgRulesMaster.Rows.Cast<DataGridViewRow>()
.Select(x => new {
RuleId = x.Cells[0].Value.ToString(),
IsWarning = x.Cells[3].Value.ToString() });
var tuples = from n in xdoc.Descendants("Rule")
from r in rules
where n.Attribute("id").Value == r.RuleId
select new { Node = n, Rule = r };
foreach(var tuple in tuples)
tuple.Node.Attribute("action").Value = tuple.Rule.IsWarning;
This is basically the same, just a bit more LINQ-y. Whether or not this is "better" is debatable. One thing I removed is the conversion of IsWarning first to string, then to int and finally back to string. It now is converted to string once and left that way.
XPath allows you to target nodes in the xml with alot of power. Microsoft's example of using the XPathNavigator to modify an XML file is as follows:
XmlDocument document = new XmlDocument();
document.Load("contosoBooks.xml");
XPathNavigator navigator = document.CreateNavigator();
XmlNamespaceManager manager = new XmlNamespaceManager(navigator.NameTable);
manager.AddNamespace("bk", "http://www.contoso.com/books");
foreach (XPathNavigator nav in navigator.Select("//bk:price", manager))
{
if (nav.Value == "11.99")
{
nav.SetValue("12.99");
}
}
Console.WriteLine(navigator.OuterXml);
Source: http://msdn.microsoft.com/en-us/library/zx28tfx1(v=vs.80).aspx

How can I get a node from an XML document based on its attribute value and into an XElement object?

I need to inject some XML into a pre-existing XML file under a certain node. Here is the code I have to create my XML:
//Define the nodes
XElement dataItemNode = new XElement("DataItem");
XElement setterNodeDisplayName = new XElement("Setter");
XElement setterNodeOU = new XElement("Setter");
//Create the tree with the nodes
dataItemNode.Add(setterNodeDisplayName);
dataItemNode.Add(setterNodeOU);
//Define the attributes
XAttribute nameAttrib = new XAttribute("Name", "OrganizationalUnits");
XAttribute displayNameAttrib = new XAttribute("Property", "DisplayName");
XAttribute ouAttrib = new XAttribute("Property", "OU");
//Attach the attributes to the nodes
setterNodeDisplayName.Add(displayNameAttrib);
setterNodeOU.Add(ouAttrib);
//Set the values for each node
setterNodeDisplayName.SetValue("TESTING DISPLAY NAME");
setterNodeOU.SetValue("OU=funky-butt,OU=super,OU=duper,OU=TMI,DC=rompa-room,DC=pbs,DC=com");
Here is the code I have so far to load up the XML document and try to get the node that I need to insert my XML under:
//Load up the UDI Wizard XML file
XDocument udiXML = XDocument.Load("UDIWizard_Config.xml");
//Get the node that I need to append to and then append my XML to it
XElement ouNode = THIS IS WHAT I DONT KNOW HOW TO DO
ouNode.Add(dataItemNode);
Here is the XML from the existing document I am trying to work with:
<Data Name="OrganizationalUnits">
<DataItem>
<Setter Property="DisplayName">TESTING DISPLAY NAME</Setter>
<Setter Property="OU">OU=funky-butt,OU=super,OU=duper,OU=TMI,DC=rompa-room,DC=pbs,DC=com</Setter>
</DataItem>
I have multiple nodes that with the name of "Data", but I need to get the node that is , and I don't know how. Just learning how to use XML with C#.
Thank you.
This will get the first Data node with Name attribute matching OrganizationalUnits:
var ouNode = udiXML
.Descendants("Data")
.Where(n => n.Attribute("Name") != null)
.Where(n => n.Attribute("Name").Value == "OrganizationalUnits")
.First();
If your document might contain Data nodes without Name attribute, extra check for null might be necessary.
Note that you can achieve the same result with XPath (this will select root Data node, you can get DataItem node using Element method):
var ouNode = udiXML.XPathSelectElement("//Data[#Name = 'OrganizationalUnits']");

How to modify an xml attribute's value?

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

Categories

Resources