NullRefernceException when adding XElement to a XDocument - c#

I have the following .xml file:
<?xml version="1.0" encoding="utf-8" ?>
<Params>
<Name>Resolver1</Name>
<RemoteHosts>
<Host>
<Name>Locale</Name>
<IP>localhost</IP>
<Port>8082</Port>
</Host>
</RemoteHosts>
</Params>
Now, when I try to add another "Host" in the "RemoteHosts" section using the following code it raises a NullReferenceException:
XDocument xmlList = XDocument.Load("NetConfig.xml");
xmlList.Element("RemoteHosts").Add(new XElement("Host",
new XElement("Name", h.name),
new XElement("IP", h.IP),
new XElement("Port", h.port)));
anyway the
xmlList.Save("NetConfig.xml");
works well, saving the new item...what's wrong?

XmlList contains only 1 node and its Params not RemoteHosts

Try xmlList.Root.Element("RemoteHosts")

Related

C# WPF Unable to write to XML file

I am new to WPF and am attempting to write a child node to an XML file. Here is the file...
<?xml version="1.0" encoding="utf-8"?>
<Sequences>
<LastSavedSequence name="Last Saved Sequence">
<Test name="Measure Battery Current(Stim)" testNumber="5" Vbat="3.7" Frequency="20" PulseWidth="500" Amplitude="1" Resistance="1600" Anode="1" Cathode="2" ActiveDischarge=""/>
<Test name="Measure Batther Current(No Stim)" testNumber="6" Vbat="2.9" Frequency="20" PulseWidth="500" Amplitude="1" Resistance="1600" Anode="1" Cathode="2" ActiveDischarge=""/>
</LastSavedSequence>
<ScottTestSequence name="Scott Test Sequence">
<Test name="VMO Status" testNumber="4" Vbat="3.7" Frequency="20" PulseWidth="1000" Amplitude="6" Resistance="3000" Anode="1" Cathode="2" ActiveDischarge=""/>
<Test name="Measure Battery Current(Stim)" testNumber="5" Vbat="3.7" Frequency="20" PulseWidth="500" Amplitude="1" Resistance="1600" Anode="1" Cathode="2" ActiveDischarge=""/>
<Test name="Measure Batther Current(No Stim)" testNumber="6" Vbat="2.9" Frequency="20" PulseWidth="500" Amplitude="1" Resistance="1600" Anode="1" Cathode="2" ActiveDischarge=""/>
</ScottTestSequence>
</Sequences>
I am attempting to create an XML child block to go within . I used stringBuilder and then am trying to do an attach child and then a .save. XMLData2 is a global list and contains a the child elements that I get in the for each. Here is my code...
public static List<System.Xml.XmlNode> xmlData2 = new List<System.Xml.XmlNode>();
XmlDocument xmlFromOutSideSequenceFile = new XmlDocument();
xmlFromOutSideSequenceFile.Load("c:\\Users/StarkS02/Documents/SavedSequenceFile.xml");
StringBuilder exampleNode = new StringBuilder();
exampleNode.Append("<");
exampleNode.Append(tbSequenceName.Text.ToString().Replace(" ", ""));
exampleNode.Append(" name=");
exampleNode.Append("'");
exampleNode.Append(tbSequenceName.Text);
exampleNode.Append("'");
exampleNode.Append(">");
foreach (XmlNode node in xmlData2)
{
XmlElement child = xmlFromOutSideSequenceFile.CreateElement(string.Empty, node.OuterXml, string.Empty);
exampleNode.Append("</");
exampleNode.Append(tbSequenceName.Text.ToString().Replace(" ", ""));
exampleNode.Append(">");
xmlFromOutSideSequenceFile.AppendChild(exampleNode);
xmlFromOutSideSequenceFile.Save("c:\\Users/StarkS02/Documents/SavedSequenceFile.xml");
I get a compiler error on the .appendChild statement that I cannot convert a stringBuilder to an XML node. This makes sense but I'm not sure how to fix it. Any ideas?
You can create an XML fragment and append to the document.
var xmlFromOutSideSequenceFile = new XmlDocument();
xmlFromOutSideSequenceFile.Load("c:\\Users/StarkS02/Documents/SavedSequenceFile.xml");
See here for more on DocumentFragment
https://msdn.microsoft.com/en-us/library/system.xml.xmldocument.createdocumentfragment(v=vs.110).aspx
var fragment = xmlFromOutSideSequenceFile.CreateDocumentFragment();
fragment.InnerXml = #"<somexml></somexml>";
xmlFromOutSideSequenceFile.DocumentElement.FirstChild.AppendChild(fragment);
See here for more on XMLNode
https://msdn.microsoft.com/en-us/library/system.xml.xmlnode(v=vs.110).aspx
Decide where you want to put it.
.FirstChild
.LastChild
.NextSibling
.ParentNode
.PreviousSibling
Hope this helps! Cheers!

C# XmlElement: Why does it always return Nulll?

I'm relatively new to C#, and just started using XmlElement and the SingleNode Method. For some reason "customSettings" keeps returning null, although the XML Document is being loaded correctly. I've checked that by loading it as a string. I've tried everything i could imagine so far including the attempt in the comment. Any help or suggestions are much appreciated. Here is my XML Doc:
EDIT: works with solution from CodingYoshi, but is there a better way?
EDIT: changed XML and code for NSGaga to resolve read only exception with NameValueCollection in user.config
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<section name="users_fächer" type="System.Configuration.NameValueSectionHandler" />
</configSections>
<users_faecher>
<add key="user1" value="value1" />
<add key="user2" value="value2" />
</users_faecher>
</configuration>
Code:
string dir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, #"Users.config");
string new_fächer = input[1];
ExeConfigurationFileMap configMap = new ExeConfigurationFileMap();
configMap.ExeConfigFilename = dir;
Configuration config = ConfigurationManager.OpenMappedExeConfiguration(configMap, ConfigurationUserLevel.None);
ConfigurationSection myParamsSection = config.GetSection("users_faecher");
string myParamsSectionRawXml = myParamsSection.SectionInformation.GetRawXml();
XmlDocument sectionXmlDoc = new XmlDocument();
sectionXmlDoc.Load(new StringReader(myParamsSectionRawXml));
NameValueSectionHandler handler = new NameValueSectionHandler();
NameValueCollection users_fächer = handler.Create(null, null, sectionXmlDoc.DocumentElement) as NameValueCollection;
users_fächer.Set(user, new_fächer);
config.Save(ConfigurationSaveMode.Modified, true);
This will get you the first add element:
doc.ChildNodes[0].NextSibling.ChildNodes[1].ChildNodes[0].ChildNodes[0];
This will get you the first add element's value attribute.
doc.ChildNodes[0].NextSibling.ChildNodes[1]
.ChildNodes[0].ChildNodes[0].Attributes["value"].Value;

output XML to dataset

I've been trying to read an xml file from an external source to get it into a dataset. I've taken the schema and compiled my class through xsd and have loaded it into the solution.
my xml:
<?xml version="1.0" encoding="UTF-8" standalone="true"?>
<CAMDealerManifest AssetURL="http://www.the placewherethefilelives.com/CAMPublic/d98c8185/" DealerCode="41065" DealerGuid="bc0d0bc8-b37b-11e3-a345-ac162dbc18f8" DealerName="Ron Hibbard Toyota" ManifestId="13" ManifestURL="http://www.toyota.com/CAMPublic/d/41065-bc0d0bc8.xml" Path="41065-bc0d0bc8" ProviderId="1011" WebsiteVendorName="WorldDealer">
<CAMCampaigns count="15" dateTime="2014-09-16T17:18:40.877-07:00">
<CAMCampaign ManifestId="13" endDate="2014-12-31T11:59:59-08:00" flightDates="08/01/14 - 12/31/14" geography="National" groupName="National" id="68" name="National - Corolla Style Elevated" priority="0" required="false" startDate="2014-08-01T12:00:00-07:00">
<CAMCreative SubGroup="Corolla Style Elevated" Id="49" Name="National - Corolla Style Elevated" ImageAltText="Toyota's national banner for the stylish 2014 Corolla" ImageSearchTerms="Toyota, 2014 Corolla, Style Elevated, New Heights" Link="New Inventory" Model="Corolla" MonthYear="08-2014" Priority="3" Required="false">
<CAMCreativeSource CAMAssetCount="1" Height="409" Width="990" MediaBinAssetId="0E1C886A-C5CE-4409-AD36-7070D614A7A6" MediaBinFileName="03-14_01_2014_nat-style-elevated_990x409_0000000460_corolla_o_xta.jpg">
<CAMAsset Path="National/Corolla-Style-Elevated/National---Corolla-Style-Elevated/990/409/" Id="1273" Name="08-14_01_National-Corolla-Style-Elevated_990x409_431_Corolla_O_xta.jpg" Height="409" Width="990" assetType="JPG" Guid="b9f4d3cd-fefd-4ff3-b209-338f409e551c" Md5Hex="3e328dc32a2db9fc1f3d6a2167d3e5d2">
<CAMTracking>
<SiteCatalyst version="1.0">
<Click tmsomni.events="event28" tmsomni.products=";08-14_01_National-Corolla-Style-Elevated_990x409_431_Corolla_O_xta;;;event28=1"/>
<Impression tmsomni.events="event29" tmsomni.products=";08-14_01_National-Corolla-Style-Elevated_990x409_431_Corolla_O_xta;;event29=1;evar43=img|evar61=corolla|evar54=o|evar49={$CAM_PAGE_POSITION}"/>
</SiteCatalyst>
</CAMTracking>
</CAMAsset>
</CAMCreativeSource>
</CAMCreative>
</CAMCampaign>
</CAMCampaigns>
<CAMExpiredCampaigns count="0" dateTime="2014-09-16T17:18:40.873-07:00"/>
</CAMDealerManifest>
I can't seem to get this xml to list or put into a dataset. I'm new to deserializing xml and could use some assistance.
Simply call ReadXml with the path to the file:
var dataSet = new DataSet();
dataSet.ReadXml(string PathToFile);
Works pretty well; will even create all the relations (notice CAMDealerManifestId in the screenshot).
Your file went in with only a modification to the XML declaration -- had to change standalone value from true to yes:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
If you're reading this in as a string, you could do something like this:
var xmlString = HoweverYouGetTheString().Split(new string[] { "\r\n" }, StringSplitOptions.None);
xmlString[0] = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>";
using (var reader = new System.IO.StringReader(String.Join("\r\n", xmlString)))
{
dataSet.ReadXml(reader);
}

Append subchildnode

I'm stuck with some task here. I want to write to xml file.
Here is the file:
<?xml version="1.0" encoding="utf-8"?>
<lists>
<plannedList>
<Skift-a></Skift-a>
<Skift-b></Skift-b>
<Skift-c></Skift-c>
<Skift-d></Skift-d>
<Skift-e></Skift-e>
</plannedList>
<requestedList>
<Skift-a></Skift-a>
<Skift-b></Skift-b>
<Skift-c></Skift-c>
<Skift-d></Skift-d>
<Skift-e></Skift-e>
</requestedList>
</lists>
then i want to use c# and for example dataset or an other method to add a jobID under the loggedIn Skift. so if Skift-a is logged on, and press a button, i want the xml file to look like this:
<?xml version="1.0" encoding="utf-8"?>
<lists>
<plannedList>
<Skift-a></Skift-a>
<Skift-b></Skift-b>
<Skift-c></Skift-c>
<Skift-d></Skift-d>
<Skift-e></Skift-e>
</plannedList>
<requestedList>
<Skift-a></Skift-a>
<jobID>1<jobID/>
<Skift-b></Skift-b>
<Skift-c></Skift-c>
<Skift-d></Skift-d>
<Skift-e></Skift-e>
</requestedList>
</lists>
And here is what I've tried so far:
XmlDocument xmldoc = new XmlDocument();
xmldoc.Load(this.Page.Server.MapPath("~/StoredData/JobsByUsers.xml"));
XmlNode Skift = xmldoc.SelectSingleNode("/requestedList/" + User.Identity.Name.ToString());
XmlNode newJobID = xmldoc.CreateNode(XmlNodeType.Element, "jobID", null);
newJobID.InnerText = topID.ToString();
Skift.AppendChild(newJobID);
xmldoc.Save(this.Page.Server.MapPath("~/StoredData/JobsByUsers.xml"));

how to check if xml document has a certain list of attributes?

i am experimenting with C# and xml, i am trying to read a XML file i want to validate if "NumberOfDays" , "NumberOfBooks", "NumberOfExam", "CurrentDate" are existing, if missing. i want to add them with there values.
i have the following xmldocument :
<?xml version="1.0" encoding="utf-8" ?>
<MySample>
<Content>
<add key="NumberOfDays" value="31" />
<add key="NumberOfBooks" value="20" />
<add key="NumberOfExam" value="6" />
<add key="CurrentDate" value="15 - Jul - 2011" />
</Content>
</MySample>
i am writing a sample application in c# using
--------Edit--------
thank you AresAvatar for your responce.
but if the value exists i would like to update its value i.e. if let's say
<add key="NumberOfExam" value="" />
i want to change the value to 6
You can get a list of which nodes exist like this:
// Get a list of which nodes exist
XmlDocument doc = new XmlDocument();
doc.LoadXml(myXml);
List<string> existingNodes = new List<string>();
XmlNodeList bookNodes = doc.SelectNodes("/MySample/Content/add");
foreach (XmlNode nextNode in bookNodes)
{
foreach (XmlAttribute nextAttr in nextNode.Attributes)
existingNodes.Add(nextAttr.InnerText);
}
You can add missing nodes like this:
// Add nodes
XmlNode addRoot = doc.SelectSingleNode("/MySample/Content");
XmlElement addme = doc.CreateElement("add");
addme.SetAttribute("NumberOfDays", "31");
addRoot.AppendChild(addme);
You can set the value of existing nodes like this:
// Update a node
foreach (XmlNode nextNode in bookNodes)
{
foreach (XmlAttribute nextAttr in nextNode.Attributes)
{
switch (nextAttr.Name)
{
case "NumberOfDays":
((XmlElement)nextNode).SetAttribute("value", "31");
break;
// etc.
}
}
}
First of all, if you have control over the generated XML (if you make it yourself), avoid using this schema:
<?xml version="1.0" encoding="utf-8" ?>
<MySample>
<Content>
<add key="NumberOfDays" value="31" />
<add key="NumberOfBooks" value="20" />
<add key="NumberOfExam" value="6" />
<add key="CurrentDate" value="15 - Jul - 2011" />
</Content>
</MySample>
It's much easier to use with that schema:
<?xml version="1.0" encoding="utf-8" ?>
<MySample>
<Content>
<Adds>
<NumberOfDays>31<NumberOfDays/>
<NumberOfBooks>20<NumberOfBooks/>
<NumberOfExam>6<NumberOfExam/>
<CurrentDate>5 - Jul - 2011<CurrentDate/>
</Adds>
</Content>
</MySample>
And then:
XmlDocument doc = new XmlDocument();
doc.Load("YourXmlPath");
XmlNode firstNode = doc["MySample"];
if(firstNode != null)
{
XmlNode secondNode = firstNode["Content"];
if(secondNode != null)
{
XmlNode thirdNode = secondNode["Adds"];
if(thirdNode != null)
{
if(thirdNode["NumberOfDays"] == null) //The "NumberOfDays" node does not exist, we create it.
{
XmlElement newElement = doc.CreateElement("NumberOfDays");
newElement.InnerXml = 31;
thirdNode.AppendChild(newElement);
}
//Do the same for the other nodes...
}
}
}
doc.Save("YourXmlPath");
Just remember to check for null on every node, or put the whole block into a try/catch.
And to save the XML once you did your changes.
XmlDocument.Load() function loads the XML in memory, so you can check for any node without making "blind loops".

Categories