C# XML getting a duplicated empty node? - c#

I am creating a xml document using the following C# code:
XmlDocument finalDoc = new XmlDocument();
//(1) the xml declaration is recommended, but not mandatory
XmlDeclaration xmlDeclaration = finalDoc.CreateXmlDeclaration("1.0", "UTF-8", null);
XmlElement root = finalDoc.DocumentElement;
finalDoc.InsertBefore(xmlDeclaration, root);
//(2) string.Empty makes cleaner code
XmlElement element1 = finalDoc.CreateElement(string.Empty, "root", string.Empty);
finalDoc.AppendChild(element1);
for (int i = 0; i < 5; i++)
{
XmlElement element2 = finalDoc.CreateElement(string.Empty,"song", string.Empty);
element2.SetAttribute("title", "title" + i);
element1.AppendChild(element2);
for (int k=0; k<5;k++)
{
XmlElement element3 = finalDoc.CreateElement(string.Empty, "line", string.Empty);
element3.InnerText = "text " + k;
element2.AppendChild(element3);
}
element1.AppendChild(element2);
}
finalDoc.Save("C:\\Users\\adm\\Downloads\\finalDoc.xml");
and I am getting the following output:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<song title="title 0" />
<song title="title 0">
<line>text 0</line>
<line>text 1</line>
<line>text 2</line>
<line>text 3</line>
<line>text 4</line>
</song>
<song title="title 1" />
<song title="title 1">
...
</song>
...
</root>
As you can see, I am having a duplicated empty "song" node for some reason, what am I missing here?
I don't see anything out of order here, could someone please help, thanks in advance.

You AppendChild 2 times element2. Remove first one
for (int i = 0; i < 5; i++)
{
XmlElement element2 = finalDoc.CreateElement(string.Empty,"song", string.Empty);
element2.SetAttribute("title", "title" + i);
for (int k=0; k<5;k++)
{
XmlElement element3 = finalDoc.CreateElement(string.Empty, "line", string.Empty);
element3.InnerText = "text " + k;
element2.AppendChild(element3);
}
element1.AppendChild(element2);
}

The line element1.AppendChild(element2); occurs twice in your for loop, third and last line in the loop.

Related

Create XML string using C# XmlElement

I am trying to create an XML string but the expected output is different from this code
XmlDocument xml = new XmlDocument();
XmlElement root = xml.CreateElement("Employee");
xml.AppendChild(root);
for (int i = 1; i < datacount; i++)
{
XmlElement child = xml.CreateElement("EmployeeName");
child.SetAttribute("value", "Name1");
root.AppendChild(child);
}
string xmlString = xml.OuterXml;
Expected output:
<?xml version="1.0" encoding="utf-8" ?>
<Employee>
<EmployeeName>Name1</EmployeeName>
<EmployeeName>Name2</EmployeeName>
</Employee>
Current output:
<?xml version="1.0" encoding="utf-8" ?>
<Employee>
<EmployeeName Value = "Name1" />
<EmployeeName Value = "Name1" />
</Employee>
XmlDocument xml = new XmlDocument();
XmlElement root = xml.CreateElement("Employee");
xml.AppendChild(root);
//Create a new node and add it to the document.
//The text node is the content of the price element.
for (int i = 1; i < datacount; i++)
{
XmlElement elem = xml.CreateElement("EmployeeName");
XmlText text = xml.CreateTextNode("Name");
xml.DocumentElement.AppendChild(elem);
xml.DocumentElement.LastChild.AppendChild(text);
}
string xmlString = xml.OuterXml;
or you can use
child.InnerText="Name1";

Check if element exists in XML using c#

Why do I get false value for hasIdentifier variable, when I see in i-th document anything_start_i.xml that there is <identifier>value</identifier> element.
XDocument doc = XDocument.Load(args[0] + "/?verb=GetRecord&metadataPrefix=p3dm&identifier=" + i);
doc.Save("anything_start" + i + ".xml");
bool hasIdentifier = doc.Elements("identifier").Any();
Console.WriteLine(hasIdentifier);
Tried with Descendants instead of Elements, and again false.
XML:
<?xml version="1.0" encoding="utf-8"?>
<OAI-PMH xmlns="..." xmlns:xsi="..." xsi:schemaLocation="...">
<responseDate>...</responseDate>
<request verb="GetRecord" identifier="1"</request>
<GetRecord>
<record>
<header>
<identifier>1</identifier>
<datestamp>...</datestamp>
</header>
<metadata>
<P3DM xmlns="..." xsi:schemaLocation="...">
<MODELINFOID>1</MODELINFOID>
<TITLE>Roth</TITLE>
....
Well, I would like to save all documents, and trying to stop saving when there is no documents any more (actually there is but without meaningful data). So, this is how i started:
static void Main(string[] args)
{
var i = 1;
bool work = true;
do{
XDocument doc = XDocument.Load(args[0] + "/?verb=GetRecord&metadataPrefix=p3dm&identifier=" + i);
bool hasIdentifier = doc.Elements("identifier").Any();
if (hasIdentifier) {
doc.Save("anything" + i + ".xml");
i++;
}else{
work = false;
}
} while (work);
XNamespace ns = "you namespace goes here";
bool hasIdentifier = doc.Descendants(ns + "identifier").Any();

how to get the values of attributes from an xml doc in c# without knowing fields or anything?

this is my xml document
<Names>
<Name1 type="M" name = "John">
</Name1>
</Names>
and I want to parse through the document so that I will get Name1,type,its value, name and its value
Use XmlDocument class and use its ChildNodes / Attributes property.
var xml = "<Names><Name type=\"M\" name=\"John\"></Name></Names>";
var doc = new XmlDocument();
doc.LoadXml(xml);
var nodes = doc.DocumentElement.ChildNodes;
foreach (XmlNode node in nodes)
{
Console.WriteLine(node.Name + " : " + node.Value);
foreach (XmlAttribute attr in node.Attributes)
{
Console.WriteLine(attr.Name + " : " + attr.Value);
}
}
You can explore further from here, like GetElementsByTagName method or recursively explore the child nodes..
string xml = #"
<parent>
<child>
<nested />
</child>
<child>
<other>
</other>
</child>
</parent>
";
XmlReader rdr = XmlReader.Create(new System.IO.StringReader(xml));
while (rdr.Read())
{
if (rdr.NodeType == XmlNodeType.Element)
{
Console.WriteLine(rdr.LocalName);
}
}
The result of the above will be
parent
child
nested
child
other

Load Specific XML Node Values C#

I am trying to get the attribute values of all nodes with the tag name "Event" into a comboBox on a WindowsForm. I have tried this code below, however, nothing populates in the comboBox.
if (selectEventComboBox.SelectedIndex != -1)
{
string filePath =
Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)
+ "\\" + selectFileComboBox.SelectedItem.ToString()
+ "dogs.xml";
XmlDocument doc = new XmlDocument();
doc.Load(filePath);
XmlNodeList eventList = doc.GetElementsByTagName("Event");
for (int count = 0; count < eventList.Count; count++)
{
selectEventComboBox.Items.Add(eventList[count].Attributes.ToString());
}
}
This works fine
XmlDocument doc = new XmlDocument();
doc.Load("myxml.xml");
XmlNode root = doc.DocumentElement;
XmlNodeList nodeList = root.SelectNodes("//Event");
for (int i = 0; i < nodeList.Count; i++)
{
Console.WriteLine("row: {0}, InnerText: {1}, ID: {2}",i, nodeList[i].InnerText, nodeList[i].Attributes["id"].Value);
}
Contents of myxml.xml
<?xml version="1.0" encoding="utf-8" ?>
<root>
<Event id="1">Event one</Event>
<Event id="2">Event two</Event>
<Event id="3">Event three</Event>
<Event id="4">Event four</Event>
</root>

Writing and then removing node from XML doc using C#/Unity3D

I am trying to add nodes to an xml document and then deleting them.
Adding nodes is working, but i cant remove nodes unless i restart the program.
The Write method:
public void writeToExistingDoc (String fileNamePath, int x, int y, int t)
{
string filename = fileNamePath;
string xPos = "" + x;
string yPos = "" + y;
string type = "" + t;
//create new instance of XmlDocument
XmlDocument doc = new XmlDocument ();
//load from file
doc.Load (filename);
//create node and add value
XmlNode node = doc.CreateNode (XmlNodeType.Element, "BUILDING", null);
XmlAttribute atr = doc.CreateAttribute ("x");
XmlAttribute atr2 = doc.CreateAttribute ("y");
XmlAttribute atr3 = doc.CreateAttribute ("type");
atr.Value = xPos;
atr2.Value = yPos;
atr3.Value = type;
node.Attributes.Append (atr);
node.Attributes.Append (atr2);
node.Attributes.Append (atr3);
//add to elements collection
doc.DocumentElement.AppendChild (node);
Debug.Log ("Element added");
//save back
doc.Save (filename);
}
and here is the Remove method:
public void removeBuildingNode (string fileNamePath, int buildingPosX, int buildingPosY)
{
XmlDocument doc = new XmlDocument ();
doc.Load (fileNamePath);
XmlNodeList nodes = doc.SelectNodes ("//BUILDING[#x='" + buildingPosX + "']");
for (int i = nodes.Count - 1; i >= 0; i--) {
Debug.Log("" + i);
nodes[i].ParentNode.RemoveChild (nodes[i]);
}
doc.Save(fileNamePath);
Debug.Log(""+buildingPosX + ", " + buildingPosY);
}
My XML doc looks like this:
<BUILDINGS ID="b">
<BUILDING x="50" y="80" type="1" />
<BUILDING x="25" y="125" type="1" />
<BUILDING x="35" y="125" type="1" />
<BUILDING x="45" y="125" type="1" />
</BUILDINGS>
As i've said, the methods work when i first run the program, use the write method, the restart the program and use the remove method. Wont work on the same running instance.
If you aren't bent on using XmlDocument, this should work...
Using: http://searisen.com/xmllib/extensions.wiki
public void removeBuildingNode (string fileNamePath, int buildingPosX, int buildingPosY)
{
XElement doc = XElement.Load(fileNamePath);
var nodesToRemove = doc.Elements("BUILDING")
.Where(xe => xe.Get("x", int.MinValue) == buildingPosX);
foreach(XElement node in nodesToRemove.ToArray())
node.Remove();
doc.Save(fileNamePath);
Debug.Log(""+buildingPosX + ", " + buildingPosY);
}

Categories

Resources