I am receiving "Object reference not set to an instance of an object." error when I try and save the value to an XML file. I have tried messing around with it for a while now. I know it works cause I use the same code (with slight difference) to save the other values to this file. This is the only one not working.
public void SAVEtxtDestination(string txtFileStuff)
{
XmlDocument myXmlDocument = new XmlDocument();
myXmlDocument.Load("C:\\Users\\fthompson11\\WebFile.xml");
XmlNode root = myXmlDocument.DocumentElement;
var targetKey = "Path";
XmlNode node = root.SelectSingleNode(string.Format("Text[#Key = '{0}']", targetKey));
node.Attributes["Value"].Value = txtFileStuff;
myXmlDocument.Save("C:\\Users\\fthompson11\\WebFile.xml");
}
Here is what my XML file looks like:
<?xml version="1.0" encoding="utf-8"?>
<!--This is to write the connection strings, text file location, and report destination.-->
<AdminPaths>
<AdminPath Name="sqlConnection1" connectionString="tacohell" />
<TextPath>
<Text Key="Path" Value="Test3" />
<Text Key="Report" Value="Test2" />
</TextPath>
</AdminPaths>
In your comment you say indicate a lower case 'v' in value nodes.attributes["value"].Value in the example it's upper upper case. Linq to XML is case sensitive, make sure the attribute name in code matches exactly with the attribute name in the file.
Related
I am trying to change the values in a Farming simulator 22 savegame xml file from C# in visual studio. There are a lot of nodes so I have reduced them to make things easier. I want to know how to replace the value in the node using C# with out having to create and rebuild the xml file from scratch.
the path to the xml file is: (C:\Users\Name\Documents\My Games\FarmingSimulator2022\savegame1\careerSavegame.xml)
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<careerSavegame revision="2" valid="true">
<settings>
<savegameName>My game save</savegameName>
<creationDate>2022-05-03</creationDate>
<mapId>MapFR</mapId>
<mapTitle>Haut-Beyleron</mapTitle>
<saveDateFormatted>2022-08-22</saveDateFormatted>
<saveDate>2022-08-22</saveDate>
<resetVehicles>false</resetVehicles>
</careerSavegame>
You can use the System.Xml.Linq namespace to access the xml file. This will load the file in the memory.
There is one class inside it, XDocument, that represents the xml document.
String filePath = "C:\Users\Name\Documents\My Games\FarmingSimulator2022\savegame1\careerSavegame.xml"
XDocument xdoc = XDocument.Load(filePath);
var element = xdoc.Elements("MyXmlElement").Single();
element.Value = "foo";
xdoc.Save("file.xml");
You can set the element variable as per the one which is needed to be replaced.
Through some research I found the solution to editing the values within the nodes. In this example I only change the value of savegameName, but it will be the same for the rest.
//Routing the xml file
XmlDocument xmlsettings = new XmlDocument();
xmlsettings.Load(#"D:\careerSavegame.xml");
//Setting values to nodes through innertext
String FarmNameSetting = "Martek Farm";
XmlNode savegameNamenode =
xmlsettings.SelectSingleNode
("careerSavegame/settings/savegameName");
savegameNamenode.InnerText = FarmNameSetting;
I've got to create a file with xml header and after that i have to put normal data, smthing like this:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Header>
<Algorithm>alg</Algorithm>
<nod2>aaa</nod2>
<nod3>bbb</nod3>
<node>
<User>
<Email />
<SessionKey />
</User>
</node>
</Header>
Data of the file....
I've already got the code to write it to the file.
Code for that part:
private void setHeader(FileStream output, string nod2, string nod3, string )
{
XmlDocument doc = new XmlDocument();
XmlNode docNode = doc.CreateXmlDeclaration("1.0", "UTF-8", "yes");
doc.AppendChild(docNode);
XmlNode header = doc.CreateElement("Header");
doc.AppendChild(header);
XmlNode algorithm = doc.CreateElement("Algorithm");
algorithm.InnerText = "alg";
header.AppendChild(algorithm);
XmlNode node2= doc.CreateElement("nod2");
node2.InnerText = nod2;
header.AppendChild(node2);
XmlNode node3= doc.CreateElement("nod3");
node3.InnerText = nod3;
header.AppendChild(node3);
XmlNode node= doc.CreateElement("node");
header.AppendChild(node);
XmlNode user1 = doc.CreateElement("User");
node.AppendChild(user1);
XmlNode mail = doc.CreateElement("Email");
user1.AppendChild(mail);
XmlNode sessionKey = doc.CreateElement("SessionKey");
user1.AppendChild(sessionKey);
doc.Save(output);
}
It work's pretty well, but when i want to read it with
private void readHeader(FileStream input, out string algorithm)
{
XmlDocument doc = new XmlDocument();
doc.Load(input);
}
I got an error that when the "Data of the file..." starts: "Data on the root level is invalid".
Is there a way to do it with the data after whole xml, or have i to add the data as a node?
This can be done in multiple ways. In comments, you've indicated that the best way is unacceptable for reasons outside the scope of the discussion. For completeness, I'm going to put that one first anyway. Skip down to tl;dr for what I think you'll have to end up doing.
The preferred way to do this is to base64 encode the encrypted data and put it in a CDATA block:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<File>
<Header>
<Algorithm>alg</Algorithm>
<nod2>aaa</nod2>
<nod3>bbb</nod3>
<node>
<User>
<Email />
<SessionKey />
</User>
</node>
</Header>
<Data><![CDATA[
ICAgIFhtbE5vZGUgYWxnb3JpdGhtID0gZG9jLkNyZWF0ZUVsZW1lbnQoIkFsZ29yaXRobSIpOw0K
ICAgIGFsZ29yaXRobS5Jbm5lclRleHQgPSAiYWxnIjsNCiAgICBoZWFkZXIuQXBwZW5kQ2hpbGQo
YWxnb3JpdGhtKTsNCiAgICBYbWxOb2RlIG5vZGUyPSBkb2MuQ3JlYXRlRWxlbWVudCgibm9kMiIp
Ow0KICAgIG5vZGUyLklubmVyVGV4dCA9IG5vZDI7DQogICAgaGVhZGVyLkFwcGVuZENoaWxkKG5v
ZGUyKTsNCiAgICBYbWxOb2RlIG5vZGUzPSBkb2MuQ3JlYXRlRWxlbWVudCgibm9kMyIpOw0KICAg
IG5vZGUzLklubmVyVGV4dCA9IG5vZDM7DQogICAgaGVhZGVyLkFwcGVuZENoaWxkKG5vZGUzKTs=
]]></Data>
</File>
That's the canonical answer to this question.
But you've told me that in your case, a requirement has been imposed that you can't do it that way.
Second choice is MIME (actually, MIME might be the first choice and the above might be the second). But I have a feeling they won't like MIME either.
Third choice, read the file as a string and search for some marker that's inserted between the XML and the binary data, something like a MIME boundary.
tl;dr
If they won't let you add such a marker to the file (and I bet they won't), search for the first occurrence of the substring "</Header>":
var xml = File.ReadAllText(filePath);
var endTag = "</Header>";
var headerXML = xml.Substring(0, xml.IndexOf(endTag) + endTag.Length);
var xdHeader = new XmlDocument();
xdHeader.LoadXml(headerXML);
I tested your code with writing directly to a file, doc.Save(#"c:\temp\test1.xml");
And loading from that file works fine. So there is nothing wrong with your xml document. Check your FileStream. Do you flush and close it properly? Does it have UTF-8 encoding?
What's the input in the node strings. Nothing that is invalid according to xml rules?
After a single root node, only comments and processor instructions can be written to xml. So, you can try to write your data in the comments.
It will look like this:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Header>
...
</Header>
<!-- your data -->
<!-- another data -->
This method has limitations: your data may not contain -- (double-hyphen) and may not end in -.
But it is better, of course, not to do so.
I 'm having problem with the code presented:
string serializedLicence = SerializationHelper.ToXML(licenceInfo);
var licenceFileXml = new XElement("Licence", new XElement("LicenceData", serializedLicence)));
XmlDocument signedLicence = SignXml(licenceFileXml.ToString(), Properties.Resources.PRIVATE_KEY);
signedLicence.Save(saveFileDialogXmlLicence.FileName);
The created file has an incorrect coding of strings send to XElement constructors aswell as the signature, that assigned with custom SignXml() method (which creates signature with XmlDocument.DocumentElement.AppendChild() method, but that's irrelevant right now). The output:
<?xml version="1.0" encoding="utf-16" standalone="yes"?>
<Licence>
<LicenceData><?xml version="1.0" encoding="utf-16"?>
<LicenceInfo
//stuff stuff stuff
</LicenceInfo></LicenceData>
<Signature><SignedInfo xmlns="h stuff stuff stuff</Signature>
</Licence>
So basically I'm taking serialized object string and put it between markers, and this part gets encoded wrong. Debugger shows me, that the text in XElement object is holding < and > just after creating it. I could parse it manually, but that's inapropriate.
Note: befeore that, I was straight signing the deserialisation xml and it worked fine, so I can't figure it out why XDocument uses different encoding than XmlSerializer/XmlDocument object.
Also: I think I could just use XmlDocument object to build the file, but I'm curious what's wrong.
You're adding serializedLicence as string, so it's treated as text, not as XML and that's why it looks like that in you document.
var licenceFileXml = new XElement("Licence",
new XElement("LicenceData",
XDocument.Parse(serializedLicence).Root)));
Here's the XML:
<PolicyChangeSet schemaVersion="2.1" username="" description="">
<Attachment name="" contentType="">
<Description/>
<Location></Location>
</Attachment>
</PolicyChangeSet>
I'm just trying to add the value "XXX" between the "location" tag.
I tried this but it isn't working:
string newValue = string.Empty;
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(AppVars.pxCentralXMLPayloadFilePath);
node = xmlDoc.SelectSingleNode("/PolicyChangeSet/Attachment/location");
node.InnerText = "XXX";
xmlDoc.Save(AppVars.pxCentralXMLPayloadFilePath);
What am I missing?!
doc.Save(#"XML FILE PATH"); //This will save the changes to the file.
Please use iteration through ChildNodes of XmlDocument - as described in walkthrough from MS Support site. According to documentation of SelectSingleNode() method:
The XmlNode should not be expected to be connected "live" to the XML
document. That is, changes that appear in the XML document may not
appear in the XmlNode, and vice versa.
Found out what the problem was CASE SENSITIVITY.
ok, so, i have an xml file that looks like this:
<?xml version="1.0"?>
<Users>
<User ID="1">
<nickname>Tom</nickname>
<password>a password</password>
<host>anemail#hello.com</host>
<email>anemail</email>
<isloggedin>false</isloggedin>
<permission>10</permission>
</User>
<User ID="2">
<nickname>ohai</nickname>
<password>sercret</password>
<host>my#host</host>
<email>my#email</email>
<isloggedin>false</isloggedin>
<permission>1</permission>
</User>
<Users>
now, first, i will have a return of what their ID number is, so, ill have "2".
from that, i will need to go into, and edit the fields in it, and resave the xml.
so basically what i need, is to open the file, find the info for User ID="2", and resave the xml, with DIFFERENT values inside of user 2, without affecting the rest of the document.
examlpe:
<User ID="2">
<nickname>ohai</nickname>
<password>sercret</password>
<host>my#host</host>
<email>my#email</email>
<isloggedin>false</isloggedin>
<permission>1</permission>
</User>
//do the alterations here, and end up with
<User ID="2">
<nickname>ohai</nickname>
<password>somthing that is different than before</password>
<host>the most current host that they were seen as</host>
<email>my#email</email>
<isloggedin>false</isloggedin>
<permission>1</permission>
</User>
etc.
Summary:
i need to open a text file, return the information via ID number, edit the information, re-save the file. without affecting anything other than user 2
~Thanks!
There are multiple ways you could do this - this is with an XmlDocument, which works in .NET 1.x and up, and works fine as long as your XML document isn't too long:
// create new XmlDocument and load file
XmlDocument xdoc = new XmlDocument();
xdoc.Load("YourFileName.xml");
// find a <User> node with attribute ID=2
XmlNode userNo2 = xdoc.SelectSingleNode("//User[#ID='2']");
// if found, begin manipulation
if(userNo2 != null)
{
// find the <password> node for the user
XmlNode password = userNo2.SelectSingleNode("password");
if(password != null)
{
// change contents for <password> node
password.InnerText = "somthing that is different than before";
}
// find the <host> node for the user
XmlNode hostNode = userNo2.SelectSingleNode("host");
if(hostNode != null)
{
// change contents for <host> node
hostNode.InnerText = "the most current host that they were seen as";
}
// save changes to a new file (or the old one - up to you)
xdoc.Save("YourFileNameNew.xml");
}
If you're using .NET 3.5 and up, you could also check into Linq-to-XML for a probably even easier way to manipulate your XML document.
Marc
Check out this question, should have your answer using Linq-to-XML. This involves writing out to a Console window, but the theory is the same.
Linq to XML - update/alter the nodes of an XML Document
You may use XmlDocument for this:
var doc = new XmlDocument();
doc.Load("1.xml");
var node = doc.SelectSingleNode(#"//User[#ID='2']");
node.SelectSingleNode("password").InnerText="terces";
doc.Save("1.xml");