First of all this is C#. I am creating a internet dashboard for a small group of colleages in the NHS.
Below is an example xml file in which I need to change the innertext of. I need to replace a specific element for example "Workshop1." Because we have a few workshops I cannot afford to use a general writer because it will replace all the information on the XML document with this one bit of code below.
<?xml version="1.0" ?>
<buttons>
<workshop1>hello</workshop1>
<url1>www.google.co.uk</url1>
I am using a switch case to select a specific workshop where you can change the name and add a URL of the workshop and using this code below will replace the whole document.
public void XMLW()
{
XmlTextReader reader = new XmlTextReader("C:\\myXmFile.xml");
XmlDocument doc = new XmlDocument();
switch (comboBox1.Text)
{
case "button1":
doc.Load(reader); //Assuming reader is your XmlReader
doc.SelectSingleNode("buttons/workshop1").InnerText = textBox1.Text;
reader.Close();
doc.Save(#"C:\myXmFile.xml");
break;
}
}
So just to clarify I want my C# program to search through the XML document find the element "Workshop1" and replace the innertext with text from a textBox. and be able to save it without replacing the whole document with one node. Thanks for looking.
Using XmlDocument and XPath you can do this
XmlDocument doc = new XmlDocument();
doc.Load(reader); //Assuming reader is your XmlReader
doc.SelectSingleNode("buttons/workshop1").InnerText = "new text";
You can use doc.Save to save the file also.
Read more about XmlDocument on MSDN.
EDIT
To save the document do this
doc.Save(#"C:\myXmFile.xml"); //This will save the changes to the file.
Hope this helps you.
Related
I want to create in an app - coded with C# - a copy of the actual element of a XMLReader object by using a XMLDocument instance.
The purpose is to get a copy of the actual reader element, so i can read the inner XML from the actual XML element without moving in the original reader.
When i try to load the reader into the XMLDocument i get the error "The document already has a 'DocumentElement' node.".
Any help would be appreciated.
XmlDocument xmlDocument = new XmlDocument();
MemoryStream streamFromReader = new MemoryStream();
xmlDocument.Load(reader); //Here i get the error
xmlDocument.Save(streamFromReader);
streamFromReader.Position = 0;
XmlReader copyReader = XmlReader.Create(streamFromReader);
sb.Append(copyReader.ReadInnerXml());
copyReader.Close();
The problem is that the reader is already positioned somewhere in the middle of the XML file, e.g.:
<Parent> <---- Position of the reader
<Child></Child>
<Child></Child>
</Parent>
<Parent>
<Child></Child>
<Child></Child>
</Parent>
The Load method starts to read the current node and also reads the siblings of the node. This leads to an invalid XML structure, because the document can only have one root element. The docs describe this behavior in the remarks section.
As for the original purpose of the code, I understand you want to perform a Peek (check the contents without advancing the reader) on the XmlReader. There are limited options to achieve this because an XmlReader operates forward-only. The answers to this question describe some options on how to read from an XmlReader without advancing it.
The answer of Markus helped me to get to the solution.
When the XMLReader is getting to an element which has subitems, i must get first the actual position within the file using the interface IXmlLineInfo.
IXmlLineInfo lineInfo = (IXmlLineInfo)reader;
int lineNumber = lineInfo.LineNumber;
int linePosition = lineInfo.LinePosition;
Then i create an instance of XmlTextReader, which reads the file to that position.
When the reminded position was arrived, the XmlTextReader contains the element and i can get the inner XML from it.
Stream stream = new MemoryStream(myFile.FileBytes);
XmlTextReader textReader = new XmlTextReader(stream);
while (textReader.LineNumber < lineNumber)
{
textReader.Read();
}
string innerXml = textReader.ReadInnerXml());
textReader.Close();
I am trying to edit the values of an xml document following the instructions found on another post here How to modify existing XML file with XmlDocument and XmlNode in C# .
here is my code
XmlDocument xml = new XmlDocument();
xml = xml.Load(#"https://www.aade.gr/sites/default/files/2020-09/SampleXML_1.1%20%20%28%CE%A4%CE%99%CE%9C-%CE%A0%CE%A9%CE%9B%CE%97%CE%A3%CE%97%CE%A3_%CE%91%CE%A5%CE%A4%CE%9F%CE%A4%CE%99%CE%9C%29%20.xml");
XmlNodeList aNodes = xml.SelectNodes("/InvoicesDoc/invoice/issuer/vatNumber");
foreach (XmlNode aNode in aNodes)
{
XmlAttribute vatAttribute = aNode.Attributes["vatNumber"];
vatAttribute.Value = "123456789";
}
xml.Save(#"C:\Users\Kostas\Desktop\mydata\infinal.xml");
My problem is that XmlNodeList aNodes will return empty; i have tried to change the xml.SelectNodes("/InvoicesDoc/invoice/issuer/vatNumber") to xml.SelectNodes("/InvoicesDoc/invoice/issuer") and all the way up to single xml.SelectNodes("/InvoicesDoc") but still XmlNodeList aNodes will return empty.
First attempts i loaded the XML doc from file and had the issue. Then i thought maybe something wrong with the file so changed the load of the file directly from the site provides this xml template i need to work on. Both options will load the file fine as i can see it when is saved but my changes will not complete since aNodes is empty and foreach loop will skip straight away.
What am i doing wrong?
thanks for your help in advance.
ps this is the xml i need to edit
https://www.aade.gr/sites/default/files/2020-09/SampleXML_1.1%20%20%28%CE%A4%CE%99%CE%9C-%CE%A0%CE%A9%CE%9B%CE%97%CE%A3%CE%97%CE%A3_%CE%91%CE%A5%CE%A4%CE%9F%CE%A4%CE%99%CE%9C%29%20.xml
Update: I just tried with another xlm found in microsoft example called books on https://learn.microsoft.com/en-us/previous-versions/windows/desktop/ms762271(v=vs.85)
XmlNodelist will also return null/empty when i look for /catalog/book . So the good side is that there is no problem with original xml file i need to edit and the bad side is that still i cannot figure out what i am doing wrong.
XmlNodeList aNodes returns null because the xml contains these namespace declarations:
<InvoicesDoc xmlns=\"http://www.aade.gr/myDATA/invoice/v1.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"
xsi:schemaLocation=\"http://www.aade.gr/myDATA/invoice/v1.0/InvoicesDoc-v0.6.xsd\"
xmlns:icls=\"https://www.aade.gr/myDATA/incomeClassificaton/v1.0\"
xmlns:ecls=\"https://www.aade.gr/myDATA/expensesClassificaton/v1.0\">
You need to manage your xml doing something like this:
XmlDocument xml = new XmlDocument();
xml.Load(#"https://www.aade.gr/sites/default/files/2020-09/SampleXML_1.1%20%20%28%CE%A4%CE%99%CE%9C-%CE%A0%CE%A9%CE%9B%CE%97%CE%A3%CE%97%CE%A3_%CE%91%CE%A5%CE%A4%CE%9F%CE%A4%CE%99%CE%9C%29%20.xml");
XmlNamespaceManager manager = new XmlNamespaceManager(xml.NameTable);
manager.AddNamespace("InvoicesDoc", "http://www.aade.gr/myDATA/invoice/v1.0");
//Example to get the root element
XmlNodeList root = xml.SelectNodes("/InvoicesDoc:InvoicesDoc", manager);
//Example to get the VatNumber tag
XmlNodeList aNodes =xml.SelectNodes("/InvoicesDoc:InvoicesDoc/InvoicesDoc:invoice/InvoicesDoc:issuer/InvoicesDoc:vatNumber", manager);
What I am trying to do is when I press a button, I load an XML file and try to add nodes to it.
XmlDocument doc = new XmlDocument();
doc.Load("XMLFILE.xml");
XmlNode Tag1 = doc.CreateElement("Tag1");
XmlNode Tag2 = doc.CreateElement("Tag2");
Tag2.InnerText = food.Text;
Tag1.AppendChild(Tag2);
XmlNode Tag3 = doc.CreateElement("Tag3");
Tag3.InnerText = games.Text;
Tag1.AppendChild(Tag3);
XmlNode Tag4 = doc.CreateElement("Tag4");
Tag4.InnerText = life.Text;
Tag1.AppendChild(Tag4);
When I run the code and click the button the file is empty and only has 1 tag which is one I made when I first created the file. So how can I load an XML and add to it?
There are two issues with the code you posted:
You created a bunch of XML nodes but I don't see anywhere that you actually add them to the document you loaded. You need to call AppendChild() on the DocumentElement or some other node that's already in the file if you want your new nodes to appear in the XML tree.
Your code is loading an XML document from disk into memory and editing it, but you are never storing the XML document back to disk again. You need to call Save() on the updated document if you want to see the changes persisted back to your file.
I'm kind of new to XML files in C# ASP.NET. I have a XML in the below format:
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<Installation>
<ServerIP>192.168.20.110</ServerIP>
<DB_Name>USTCKT1</DB_Name>
<Username>jorame</Username>
<Password>Cru$%e20</Password>
<Table_PreFix>TCK</Table_PreFix>
</Installation>
I need to change the values within each element. For example, when an user clicks I should be able to replace 192.168.20.110 with 192.168.1.12.
How can I accomplish this? Any help will be really appreciated.
You should look at using the methods in the XDocument class. http://msdn.microsoft.com/en-us/library/bb301598.aspx
Specifically look at the methods: Load(string) - to load an XML file, Element() - to access a specific element and Save(string) - to save the XML document. The page on Element() has some sample code which can help.
http://msdn.microsoft.com/en-us/library/system.xml.linq.xcontainer.element.aspx
You can do something like this using the XDocument class:
XDocument doc = XDocument.Load(file.xml);
doc.Element("Installation").Element("ServerIP").Value = "192.168.1.12";
//Update the rest of the elements
doc.Save(file.xml);
More Details
If you run into namespace issues when selecting your elements you will need to include the xml namespace in the XElement selectors eg doc.Element(namspace + "Installation")
In general, you can do it in the following steps:
Create a new XmlDocument object and load the content. The content might be a file or string.
Find the element that you want to modify. If the structure of your xml file is too complex, you can use xpath you find what you want.
Apply your modification to that element.
Update your xml file.
Here is a simple demo:
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load("file.xml"); // use LoadXml(string xml) to load xml string
string path = "/Installation/ServerIP";
XmlNode node = xmlDoc.SelectSingleNode(path); // use xpath to find a node
node.InnerText = "192.168.1.12"; // update node, replace the inner text
xmlDoc.Save("file.xml"); // save updated content
Hope it's helpful.
I've written a code generator, that generates C# files. If the file being generated is new, I need to add a reference to it to our .csproj file. I have the following method that adds a node to a .csproj file.
private static void AddToProjectFile(string projectFileName, string projectFileEntry)
{
StreamReader streamReader = new StreamReader(projectFileName);
XmlTextReader xmlReader = new XmlTextReader(streamReader);
XElement element;
XNamespace nameSpace;
// Load the xml document
XDocument xmlDoc = XDocument.Load(xmlReader);
// Get the xml namespace
nameSpace = xmlDoc.Root.Name.Namespace;
// Close the reader so we can save the file back.
streamReader.Close();
// Create the new element we want to add.
element = new XElement(nameSpace + "Compile", new XAttribute("Include", projectFileEntry));
// Add the new element.
xmlDoc.Root.Elements(nameSpace + "ItemGroup").ElementAt(1).Add(element);
xmlDoc.Save(projectFileName);
}
This method works fine. However, it doesn't add the node on a new line. It will append it to the previous line in the .csproj file. This makes for a bit of a mess when doing TFS merging. How can I add the new node on a new line?
Why are you using StreamReader and then XmlTextReader? Just pass the filename to the XDocument.Load. Then everything works as you would expect.
If you create the reader on your own XDocument can't modify its settings and thus the reader will report whitespaces which are then stored in the XLinq tree and when written out they disable automatic formatting in the writer. So you can either set IgnoreWhitespaces to true on your reader, or pass the input just as a filename, which will let XDocument use its own settings which will include IgnoreWhitespaces.
As a side note, please don't use XmlTextReader, a more spec compliant XML reader is created when you call XmlReader.Create.