Swapping nodes in xmlNodeList C# - c#

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);

Related

Add data to a row var xmlDocument in C# Winforms

I got a xml File like this and I want to add a /row/var to this file. For example, I want to add name="Test1" value="192.178.123.1" and the xml file will add a /var like <var name="Test1" value="192.178.123.1"/>. How could I do?
<DNS>
<row>
<var name="Viettel" value="192.168.1.1"/>
<var name="Google" value="192.182.11.2" />
<var name="Singapore" value="165.21.83.88" />
<var name="Verizon" value="4.2.2.1" />
<var name="VNPT" value="203.162.4.191" />
<var name="FPT" value="203.113.131.1" />
<var name="OpenDNS" value="210.245.31.130" />
<var name="Cloudflare" value="208.67.222.222" />
<var name="Norton" value="1.1.1.1" />
<var name="Viettel" value="198.153.192.1" />
<var name="Dnsadvantage" value="192.168.1.1" />
<var name="Hi-Teck" value="1156.154.70.1" />
<var name="Viettel" value="209.126.152.184" />
</row>
</DNS>
This is my code currently. But it doesn't work.
XmlDocument xdoc = new XmlDocument();
xdoc.Load(#"E:\Applications\Visual\C#\Forms\Test\XMLFile1.xml");
XmlNode rootNode = xdoc.DocumentElement;
XmlNode serverPathNode = xdoc.CreateElement("Test1");
serverPathNode.InnerText = "192.178.123.1";
rootNode.AppendChild(serverPathNode);
xdoc.Save(#"E:\Applications\Visual\C#\Forms\Test\XMLFile1.xml");
this is what you need to do (comments inside):
XmlDocument xdoc = new XmlDocument();
xdoc.Load(#"E:\Applications\Visual\C#\Forms\Test\XMLFile1.xml");
//find the row node to be able to add to him more "var" nodes
XmlNode rowNode = xdoc.SelectSingleNode("/DNS/row");
//create new "var" node
XmlNode serverPathNode = xdoc.CreateElement("var");
//the details are attributes and not nodes so we add them as attributes to the var node
XmlAttribute xmlAttribute = xdoc.CreateAttribute("name");
xmlAttribute.Value = "Test1";
serverPathNode.Attributes.Append(xmlAttribute);
xmlAttribute = xdoc.CreateAttribute("value");
xmlAttribute.Value = "192.178.123.1";
serverPathNode.Attributes.Append(xmlAttribute);
//add the var node to the row node
rowNode.AppendChild(serverPathNode);
xdoc.Save(#"E:\Applications\Visual\C#\Forms\Test\XMLFile1.xml");

Adding Xml Attribute to All elements except root Node

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");

Adding XML values to dropdownlist, c#

I've been messing around with the following code to add each node in an xml fileto a dropdown list but with incorrect results so far.
XmlDocument XmlDoc = new XmlDocument();
XmlDoc.Load(Server.MapPath("~/Upload/" + FileUpload1.FileName));
XmlNodeList question = XmlDoc.GetElementsByTagName("row");
foreach(XmlNode Node in question)
{
string answer = Node["var"].Attributes["name"].InnerText;
string ques = Node["var"].InnerText;
DropDownList1.Items.Add(new ListItem(answer, ques));
}
Here is my xml file
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<root>
<row>
<var name="Name" value="Garcia" />
<var name=" Surname" value=" Jose" />
<var name=" Country" value=" Cuba" />
<var name=" Job" value="Software Developer" />
<var name=" Cabin" value="345A" />
</row>
<row>
<var name="Name" value="Lenon" />
<var name=" Surname" value="Tim" />
<var name=" Country" value="USA" />
<var name=" Job" value="SoftwareDeveloper" />
<var name=" Cabin" value="444" />
</row>
<row>
<var name="Name" value="Rusell" />
<var name=" Surname" value=" Anthony" />
<var name=" Country" value=" UK" />
<var name=" Job" value="Web Designer" />
<var name=" Cabin" value="345" />
</row>
<row>
<var name="Name" value="Wolf" />
<var name=" Surname" value=" Werner" />
<var name=" Country" value=" Germany" />
<var name=" Job" value="Linux IT" />
<var name=" Cabin" value="234 " />
</row>
</root>
What I need to do is just populate a drop down list with the values Name,Surname,Country,Job and Cabin,so the user can select these values to manipulate the data. I realise with the answer tag im accessing the values also I was trying different things from code ive saw.
The results im getting in my dropdown list from this code is
Name
Name
Name
Name
Im adding the first attribute of each node, but what I need to do is add every value from just one node. NOTE: The xml files il be working with will have different values and names etc so hardcoding is not an option.
If anyone could help Id appreciate it, thank you.
XDocument xml = XDocument.Load(Server.MapPath("~/Upload/" + FileUpload1.FileName));
foreach (var el in xml.Document.Descendants().First().Descendants().First().Descendants())
{
DropDownList1.Items.Add(new ListItem(el.Attribute(XName.Get("name")).Value, Value = el.Value));
}
This is something that you should use DataBinding to accomplish. This blog post has a good example of how you would do this for ASP.NET, which would also apply to WinForms. The key function is:
//populates the dropdownlist from xml file
public void PopulateDDLsFromXMLFile()
{
DataSet ds = new DataSet();
ds.ReadXml(MapPath("~/Resources/XMLFile.xml"));
//now define datatext field and datavalue field of dropdownlist
ddlName.DataTextField = "Name";
ddlName.DataValueField = "Name";
...
//now bind the dropdownlist to the dataview
ddlName.DataSource = ds;
ddlName.DataBind();
}
For some more information on databinding, you could read the following: ASP.NET, WinForms, WPF.
I'm not exactly sure what you're doing with the drop down list, but you can use the following code to get to the individual values you want:
XmlDocument XmlDoc = new XmlDocument();
XmlDoc.Load(Server.MapPath("~/Upload/" + FileUpload1.FileName));
string searchpath = "//root//row";
XmlNodeList xmlnodes = XmlDoc.SelectNodes(searchpath);
foreach (XmlNode node in xmlnodes)
{
string name = node.SelectSingleNode("//var[#name='Name']").Attributes["value"].InnerXml;
string surname = node.SelectSingleNode("//var[#name=' Surname']").Attributes["value"].InnerXml;
string Country = node.SelectSingleNode("//var[#name=' Country']").Attributes["value"].InnerXml;
string Job = node.SelectSingleNode("//var[#name=' Job']").Attributes["value"].InnerXml;
string Cabin = node.SelectSingleNode("//var[#name=' Cabin']").Attributes["value"].InnerXml;
}
Are you saying that you want to show Garcia, Lenon,Rusell and Wolf in the ddl? if so, just change your :
Node["var"].Attributes["name"].InnerText;
to
Node["var"].Attributes["value"].Value;

C# Xml attribute values to string variable

Hey I was wondering if anyone could help to save the value of my xml doc to a c# variable. It is to help with a larger program feature. The XML layout is:
<row>
<var name="bud" value="45" />
<var name="acc" value="345" />
</row>
<row>
<var name="bud" value="45" />
<var name="acc" value="345" />
</row>
I would like to extract the value of bud and store it as a string in my c# code
thanks for any help guys I appreciate it.
XML has to be valid so added a root element.
XML:
<foo>
<row>
<var name="bud" value="45" />
<var name="acc" value="345" />
</row>
<row>
<var name="bud" value="45" />
<var name="acc" value="345" />
</row>
</foo>
Code:
This will return a List with the values of all variables "var" in your XML named "bud" and finally create a comma separated string with all the values.
string xml = "<foo><row><var name=\"bud\" value=\"45\" /><var name=\"acc\" value=\"345\" /></row><row><var name=\"bud\" value=\"45\" /><var name=\"acc\" value=\"345\" /></row></foo>";
XDocument doc = XDocument.Parse(xml);
var budValues =(from c in doc.Descendants("var")
where c.Attribute("name").Value == "bud"
select c.Attribute("value").Value).ToList();
string myBuddy = string.Join(",", budValues);
Your xml is not valid. It requires a single root node.
Here is simple solution using XPath:
XmlDocument xDoc = new XmlDocument();
xDoc.LoadXml(#"
<dataset><row>
<var name=""bud"" value=""45"" />
<var name=""acc"" value=""345"" />
</row>
<row>
<var name=""bud"" value=""45"" />
<var name=""acc"" value=""345"" />
</row></dataset>");
XmlNode node = xDoc.SelectSingleNode("/dataset/row/var[#name='bud']");
string value = node.Attributes["value"].Value;
This gets only the first of the matches where #name='bud'. Checkout XPath to adjust your result. (it's pretty powerful)

Xpath and regex for autocompletion filter

I have got a huge xml document.
something like that
<?xml version="1.0" encoding="utf-8"?>
<elements>
<element id="1" name="france" />
<element id="2" name="usa" />
<element id="3" name="Spaïn" />
<element id="4" name="spain and africa" />
<element id="5" name="italie and Spâin" />
</elements>
I want to have something like this :
string str = "spain";
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(myXML);
// Xpath with regex or something very veloce
XmlNodeList xmlNodeList = xmlDoc.SelectNodes("//element"+ something);
And the xmlNodeList will contains :
<element id="3" name="Spaïn" />
<element id="4" name="france with spâin and africa" />
<element id="5" name="italie and Spain" />
it must ignore the case
And accent
for the moment I've
XmlNodeList xmlNodeList = xmlDoc.SelectNodes("/*/*[contains(concat(' ',translate(translate(#n,translate(#n, 'aaabcdefghiiijklmnopqrstuvwxyzâÂABCDEFGHïÏIJKLMNOPQRSTUVWXYZ', ''),''), 'âÂABCDEFGHïÏIJKLMNOPQRSTUVWXYZ','aaabcdefghiiijklmnopqrstuvwxyz'),' '),' "+prefix+" ')]");
where #n = #name and prefix is maybe : "spain" or "Spain" or "Spaïn" and it give me 0 solution
Use
//element[contains(concat(' ',translate(#name,'SPAIN','spain'),' '),' spain ')]
Edit: Now, the question has changed, but the answer remains...
Just add these changes in the translation pattern like:
//element[contains(concat(' ',
translate(#name,
'SPAÂâIÏïN',
'spaaaiiin'),
' '),
' spain ')]
Note: Of course, a more general expression would need a more general translation pattern.
string str = "spain";
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(myXML);
// Xpath with regex or something very veloce
XmlNodeList xmlNodeList = xmlDoc.SelectNodes("//element[contains(#name,'spain')]");
UPDATE:
As the original problem was changed adding the requirement to recognize the word "Spain" not only in all possible capitalizations but also including accented characters, I have updated the solution below so that now "Spain" with â and/or ïÏ is correctly recognized.
Here is a more generic solution than that of #Alejandro:
If we want to select all elements, whose name attribute contains the word "Spain" in any capitalization and if the possible word delimiters are all non-alphabetic characters, then
This XPath expression:
/*/*[contains(
concat(' ',
translate(translate(#name,
translate(#name, $vAlpha, ''),
' '),
$vUpper,
$vLower),
' '
),
' spain '
)
]
when applied on this XML document:
<elements>
<element id="1" name="france" />
<element id="2" name="usa" />
<element id="3" name="Spaïn" />
<element id="4" name="france with spâin and africa" />
<element id="5" name="-Spain!" />
<element id="6" name="spain and africa" />
<element id="7" name="italie and Spain." />
</elements>
selects the following elements:
<element id="3" name="Spaïn"/>
<element id="4" name="france with spâin and africa"/>
<element id="5" name="-Spain!"/>
<element id="6" name="spain and africa"/>
<element id="7" name="italie and Spain."/>
In the above XPath expression $vLower, $vUpper must be substituted with (respectively):
'aaabcdefghiiijklmnopqrstuvwxyz'
and
'âÂABCDEFGHïÏIJKLMNOPQRSTUVWXYZ'
$vAlpha must be substituted by the concatenation of $vLower and $vUpper .

Categories