I have the following XML File:
<order id="1234">
<users>
<user id="102030" nick="nickname" done="false" />
<user id="123456" nick="nickname" done="false" />
</users>
<machines>
<machine id="123" sd="123" ref="" done="false" />
<machine id="456" sd="456" ref="" done="false" />
<machine id="789" sd="789" ref="" done="false" />
</machines>
</order>
I want to delete the user with the id 102030, so the xml looks like this:
<users>
<user id="123456" nick="nickname" done="false" />
</users>
<machines>
<machine id="123" sd="123" ref="" done="false" />
<machine id="456" sd="456" ref="" done="false" />
<machine id="789" sd="789" ref="" done="false" />
</machines>
</order>
This is my code which doesn't work:
XmlDocument doc = XmlDocument.Load(path);
XmlNodeList nodes = doc.GetElementsByTagName("users");
foreach(XmlNode node in nodes){
foreach(XmlAttribute attribute in node.Attributes){
if(attribute.Name== "id" && attribute.Value == "102030"){
node.RemoveAll();
}
}
}
doc.Save(path);
I am a newbie in C# so I need every help!
Thanks in advance, geibi
XmlNode.RemoveAll() does not remove a node. Instead it:
Removes all the child nodes and/or attributes of the current node.
Thus, instead you need to remove the node from its parent:
node.ParentNode.RemoveChild(node);
Related
I have this xml
<Folder.FolderStructure
xmlns:i="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://schemas.datacontract.org/2004/07/FileSiteAPI.Models">
<a_attr i:nil="true" />
<checkedout>false</checkedout>
<children>
<Folder.FolderStructure>
<checkedout>false</checkedout>
<children />
<created>2018-11-29T13:58:57</created>
<edited>2018-11-29T13:58:57</edited>
<extension>MSG</extension>
<id>36878331</id>
<rootfolder>false</rootfolder>
<searchfolder>false</searchfolder>
<size>29696</size>
<state i:nil="true" />
<version>1</version>
</Folder.FolderStructure>
<Folder.FolderStructure>
<checkedout>false</checkedout>
<children />
<created>2019-01-15T10:18:03</created>
<edited>2019-01-15T10:18:03</edited>
<extension>DOCX</extension>
<id>37584622</id>
<rootfolder>false</rootfolder>
<searchfolder>false</searchfolder>
<size>42345</size>
<state i:nil="true" />
<version>1</version>
</Folder.FolderStructure>
<Folder.FolderStructure>
<a_attr i:nil="true" />
<checkedout>false</checkedout>
<children i:nil="true" />
<created>0001-01-01T00:00:00</created>
<edited>0001-01-01T00:00:00</edited>
<extension i:nil="true" />
<id>2478514</id>
<rootfolder>false</rootfolder>
<searchfolder>false</searchfolder>
<size>0</size>
<state i:nil="true" />
<version>0</version>
</Folder.FolderStructure>
</children>
<created>0001-01-01T00:00:00</created>
<edited>0001-01-01T00:00:00</edited>
<extension i:nil="true" />
<id>2469288</id>
<rootfolder>false</rootfolder>
<searchfolder>false</searchfolder>
<size>72041</size>
<state i:nil="true" />
<text>Public</text>
<version>0</version>
</Folder.FolderStructure>
but when I parse it and try to read the 3 Folder.FolderStructure elements, it comes back with empty set.
XElement folder_xml = XElement.Parse(xml_str);
List<XElement> elements = folder_xml.Elements("Folder.FolderStructure").ToList();
Console.WriteLine(elements.Count);
Anyone know what's wrong?
You need to define the namespace and use Descendants instead of Elements:
XElement folder_xml = XElement.Parse(xml_str);
XNamespace ns = "http://schemas.datacontract.org/2004/07/FileSiteAPI.Models";
var elements = folder_xml.Descendants(ns + "Folder.FolderStructure").ToList();
Console.WriteLine(elements.Count);
I have the following xml file and want to add a new parent node after the last existing node.
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<testsuite id="" name="Test Projekt test">
<node_order />
<details />
<testsuite id="" name="Test Suite 1">
<node_order />
<details />
<testsuite id="" name="Test Suite Operation 2">
<node_order />
<details />
</testsuite>
</testsuite>
</testsuite>
<new node here>
i tryed to use the following code but it didnĀ“t worked
XmlElement testsuite = doc_save.CreateElement("testsuite");
XmlAttribute ID = doc_save.CreateAttribute("id");
XmlAttribute Name = doc_save.CreateAttribute("name");
XmlElement node_order = doc_save.CreateElement("node_order");
XmlElement details = doc_save.CreateElement("details");
doc_save.DocumentElement.AppendChild(testsuite);
testsuite.Attributes.Append(ID);
testsuite.Attributes.Append(Name);
testsuite.AppendChild(node_order);
testsuite.AppendChild(details);
How can I do this?
Expanding on the comment by #hotfix, rename your root element and when I ran your code it was working for me. See the XML and code I was using below.
XML:
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<testsuites id="" name="Test Projekt test">
<node_order />
<details />
<testsuite id="" name="Test Suite 1">
<node_order />
<details />
<testsuite id="" name="Test Suite Operation 2">
<node_order />
<details />
</testsuite>
</testsuite>
<testsuite id="" name="">
<node_order />
<details />
</testsuite>
</testsuites>
Code:
XmlDocument document = new XmlDocument();
document.Load(#"your\xml\file");
XmlElement testsuite = document.CreateElement("testsuite");
XmlAttribute ID = document.CreateAttribute("id");
XmlAttribute Name = document.CreateAttribute("name");
XmlElement node_order = document.CreateElement("node_order");
XmlElement details = document.CreateElement("details");
document.DocumentElement.AppendChild(testsuite);
testsuite.Attributes.Append(ID);
testsuite.Attributes.Append(Name);
testsuite.AppendChild(node_order);
testsuite.AppendChild(details);
document.Save(#"your\xml\file");
I am trying to add new attribute to my xml files in c#. my xml file format is shown below:
<Root MessageOfRoot="Welcome to Xml">
<Header Size="36">
<Parameter Name="ID" Index="0" Value="23" />
<Parameter Name="Name" Index="4" Value="Uncle Bob" />
<Parameter Name="Number" Index="8" Value="4" />
</Header>
<Body Size="0">
<Parameter Index="0" UnitNumber="0" Name="UnitBarcode" Type="Integer" />
<Parameter Index="4" PromotionId="0" Name="PromotionalUnit" Type="Integer" />
</Body>
</Root>
I want to add new attribute my xml file which should be like:
<Root MessageOfRoot="Welcome to Xml">
<Header Size="36" NewAttr="1">
<Parameter Name="ID" Index="0" Value="23" NewAttr="1"/>
<Parameter Name="Name" Index="4" Value="Uncle Bob" NewAttr="1"/>
<Parameter Name="Number" Index="8" Value="4" NewAttr="1"/>
</Header>
<Body Size="0" NewAttr="1">
<Parameter Index="0" UnitNumber="0" Name="UnitBarcode" Type="Integer" NewAttr="1"/>
<Parameter Index="4" PromotionId="0" Name="PromotionalUnit" Type="Integer" NewAttr="1"/>
</Body>
</Root>
To do that i write the following code but i am having problem with adding newAttr to all nodes. How can i add NewAttr to my new xml file?
XmlDocument doc = new XmlDocument();
doc.Load("Path of xml");
XmlAttribute NewAttr = doc.CreateAttribute("NewAttr ");
countAttr.Value = "1";
XmlWriter writer = XmlWriter.Create("output.xml", settings);
You can use the following command to load the XML file:
XDocument doc = XDocument.Load(#"C:\Users\myUser\myFile.xml");
Then you can invoke a function that recursively accesses all nodes of the XML starting from the children nodes of the Root element:
AddNewAttribute(doc.Root.Elements());
The function can be like so:
public static void AddNewAttribute(IEnumerable<XElement> elements)
{
foreach (XElement elm in elements)
{
elm.Add(new XAttribute("newAttr", 1));
AddNewAttribute(elm.Elements());
}
}
Finally, you can save the XML back to the original file using:
doc.Save(#"C:\Users\myUser\myFile.xml");
Assuming having the following xml
<test>
<step>
<var name="name1" />
<var name="name2" />
</step>
<step>
<var name="name3" />
<var name="name4" />
</step>
<step>
<var name="name5" />
<var name="name6" />
</step>
</test>
I m using XmlNodeList, seperated by "step". Is there a way to swap or replace a step directly in the xmlnodelist?
Need to make it like this:
<test>
<step>
<var name="name3" />
<var name="name4" />
</step>
<step>
<var name="name1" />
<var name="name2" />
</step>
<step>
<var name="name5" />
<var name="name6" />
</step>
</test>
You can use XDocument class instead of XMLDocument. This will swap the var nodes name3 with name6.
using System.Linq;
using System.Xml.Linq;
class Test
{
static void Main()
{
XDocument document = XDocument.Load("test.xml");
Swap("name3", "name6", document);
document.Save("test.xml");
}
static void Swap(string nameOne, string nameTwo, XDocument document)
{
var nameOneNode = document.Descendants("var").FirstOrDefault(p => p.Attribute("name").Value == nameOne);
var nameTwoNode = document.Descendants("var").FirstOrDefault(p => p.Attribute("name").Value == nameTwo);
nameOneNode.Attribute("name").Value = nameTwo;
nameTwoNode.Attribute("name").Value = nameOne;
}
}
The order of the nodes in an XML file does not necessarily have to be kept when the XML file is read. For example, if your file looks like this:
<xmlcontent>
<node value="Hello" />
<node value="World" />
</xmlcontent>
The XML read may return the nodes like this:
<xmlcontent>
<node value="World" />
<node value="Hello" />
</xmlcontent>
To apply something like an "order" to XML nodes, you need to add an attribute you can sort by, like
<xmlcontent>
<node index="1" value="Hello" />
<node index="2" value="World" />
</xmlcontent>
In that case, "swapping" two elements would come down to swapping the index values.
Finally managed to do it, here is the code:
XmlDocument xml;
XmlNodeList xmlList;
xml = new XmlDocument();
xml.Load(path);
xmlList = xml.GetElementsByTagName("step");
XmlNode refNode = xmlList[1];
XmlNode newNode = xmlList[0];
xml.DocumentElement.InsertAfter(newNode, refNode);
I am trying to get both the next and previous elements of the current element
Here is the xml
<template id="9">
<tabs>
<tab>
<name>test</name>
<description />
</tab>
<tab>
<name>test3</name>
<description />
</tab>
<tab>
<name>test7</name>
<description />
</tab>
</tabs>
<tabs />
<tabs />
</template>
The current node is the tab with
test3
here is the code i am using
var doc = XDocument.Parse(q.XMLtext);
var tabs = doc.ElementOrDefault("template").ElementOrDefault("tabs").Elements();
var Current = doc.ElementOrDefault("template")
.ElementOrDefault("tabs")
.ElementsOrDefault("tab")
.ElementsOrDefault("name")
.Where(x => x.Value == name);
//get the next and previous nodes here
How about this:
var previous = Current.PreviousNode;
var next = Current.NextNode;
The only issue with this is it will return comments and other things that are nodes, but based on your XML this would still work for you.