Append to existing Xml in C# - c#

I have a Xml File below that I am trying to load in to visual studio then append another entry for D100 to the file then write or append it 1000 times.
The code below saves the document but nothing gets appended.
<flp:Tab xmlns:flp="http://www.w3.org/2001/XMLSchema" Title="Testing">
<flp:Form Number="0" id="1005" />
<flp:Rev Time="2013-01-21T15:08:00">
<flp:Author Name="Brad" Aid="15" />
</flp:Rev>
<flp:Designs Id="D100">
<flp:D100 Number="1">
<flp:Code>A</flp:Code>
<flp:Documented>true</flp:Documented>
<flp:Note>In Process</flp:Note>
<flp:Testers>
<flp:Tester Name="David">
<flp:Titles>
<flp:Title Number="0" Name="Entry 1">
<flp:Start>Begin</flp:Start>
<flp:Finish>End</flp:Finish>
</flp:Title>
</flp:Titles>
</flp:Tester>
</flp:Testers>
<flp:TestGivers>
<flp:TestGiver Name="James" />
</flp:TestGivers>
<flp:IsRequired>true</flp:IsRequired>
<flp:IsOptional>false</flp:IsOptional>
</flp:D100>
</flp:Designs>
</flp:Tab>
I am trying to append and write out the information 1000 times in the Xml File
Here is my C# code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Xml;
namespace AppendXml
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Button_Click_1(object sender, RoutedEventArgs e)
{
XmlDocument doc = new XmlDocument();
doc.Load("C:\\Desktop\\Temp.xml");
//XmlElement root = doc.CreateElement("Tab");
XmlElement D100 = doc.CreateElement("D100");
D100.SetAttribute("Number", "2");
XmlElement Code = doc.CreateElement("Code");
Code.InnerText = "B";
XmlElement Documented = doc.CreateElement("Documented");
Documented.InnerText = "false";
XmlElement Note = doc.CreateElement("Note");
Note.InnerText = "Complete";
XmlElement Tester = doc.CreateElement("Tester");
Tester.SetAttribute("Name", "John");
XmlElement Title = doc.CreateElement("Title");
Title.SetAttribute("Number", "0");
Title.SetAttribute("Name", "Ronald");
XmlElement Start = doc.CreateElement("Start");
Start.InnerText = "Begin";
XmlElement Finish = doc.CreateElement("Finish");
Finish.InnerText = "End";
XmlElement TestGiver = doc.CreateElement("TestGiver");
TestGiver.SetAttribute("Name", "Jeremy");
XmlElement IsRequired = doc.CreateElement("IsRequired");
IsRequired.InnerText = "true";
XmlElement IsOptional = doc.CreateElement("IsOptional");
IsOptional.InnerText = "false";
D100.AppendChild(IsOptional);
D100.AppendChild(IsRequired);
D100.AppendChild(TestGiver);
D100.AppendChild(Finish);
D100.AppendChild(Start);
D100.AppendChild(Title);
D100.AppendChild(Tester);
D100.AppendChild(Note);
D100.AppendChild(Documented);
D100.AppendChild(Code);
//root.AppendChild(D100);
//doc.AppendChild(root);
doc.Save("test13.xml");
}
}
}
The document saves but noting appends. What am I leaving out?

You should append D100 to flp:Designs - now you are not appending it to anything, hence nothing gets added to the document:
XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.NameTable);
nsmgr.AddNamespace("flp", "http://www.w3.org/2001/XMLSchema");
XmlNode designs = doc.SelectSingleNode("//flp:Designs", nsmgr);
designs.AppendChild(D100);
You are also creating D100 in the default namespace, probably you want to create it in the http://www.w3.org/2001/XMLSchema namespace with flp prefix as the rest of the XML:
XmlElement D100 = doc.CreateElement("flp", "D100", "http://www.w3.org/2001/XMLSchema");
Lastly: http://www.w3.org/2001/XMLSchema is a standard namespace, that here is used for some custom XML, this is in general wrong.

Related

Update multiple XML nodes that match an Xpath query C#

I am trying to update the content of multiple nodes that match a specific xpath. For example, in the below example, I want to update any attribute1 node that currently is '2' with 'Hello'. What is the best way to do this?
(DotNetFiddle Here)
using System;
using System.IO;
using System.Xml;
using System.Linq;
public class Program
{
public static void Main()
{
XmlDocument job = new XmlDocument();
job.LoadXml(#"<parent>" +
"<report>" +
"<main>" +
"<attribute1>2</attribute1>"+
"<attribute1>2</attribute1>"+
"<attribute1>3</attribute1>"+
"</main>"+
"</report>" +
"</parent>");
string newAttribute1Value = "Hello";
//How do I update both attribute1's where value=2?
}
This may could help you :
using System;
using System.IO;
using System.Xml;
using System.Linq;
public class Program
{
public static void Main()
{
XmlDocument job = new XmlDocument();
job.LoadXml(#"<parent>" +
"<report>" +
"<main>" +
"<attribute1>2</attribute1>"+
"<attribute1>2</attribute1>"+
"<attribute1>3</attribute1>"+
"</main>"+
"</report>" +
"</parent>");
string newAttribute1Value = "Hello";
//How do I update both attribute1's where value=2?
// getting the list of nodes with XPath query :
XmlNodeList nodes = job.SelectNodes("//attribute1[text()=2]");
foreach (XmlNode child in nodes)
{
// replacing the old value with the new value
child.InnerText = newAttribute1Value ;
}
}

Read XElement Fragment from xml file to XElement Element

I have xml fragment in an xml-File. The fragment has tags with namespace.
How can I read that xml fragment, which represent exactly an XElement element ?
<node id="n0::n0">
<data key="d6">
<y:ShapeNode>
<y:Geometry height="91.44" width="59.49119999999999" x="364.256180835285" y="-698.4404365079365"/>
<y:Fill color="#FFCC00" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="internal" modelPosition="t" textColor="#000000" visible="true" width="48.677734375" x="5.406732812499968" y="4.0">MELEIN</y:NodeLabel>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" modelName="custom" textColor="#000000" visible="true" width="27.35546875" x="16.067865624999968" y="20.843814062500087">8,00<y:LabelModel>
<y:SmartNodeLabelModel distance="4.0"/>
</y:LabelModel>
<y:ModelParameter>
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="-0.5" nodeRatioX="0.0" nodeRatioY="-0.2720492775317138" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
</y:ModelParameter>
</y:NodeLabel>
<y:Shape type="rectangle"/>
</y:ShapeNode>
</data>
</node>
I tried a lot of different ways the last one nearly comes to the target
var mngr = new System.Xml.XmlNamespaceManager(new System.Xml.NameTable());
mngr.AddNamespace(string.Empty, "urn: ignore"); // or proper URL
mngr.AddNamespace("y", "urn:ignore"); // or proper URL
var parserContext = new System.Xml.XmlParserContext(null, mngr, null, System.Xml.XmlSpace.None, null);
var txtReader = new System.Xml.XmlTextReader("block.graphml", System.Xml.XmlNodeType.Element, parserContext);
var ele = XElement.Load(txtReader);
but it crashes in the last line with System.InvalidOperationException
Is there any easy way to import xml fragment to an existing xelement?
I would prefer the way XElement.load("block.graphml"); This didn't work at all.
Thanks for your tips
You can do it like this
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = #"c:\temp\test.txt";
static void Main(string[] args)
{
string input = File.ReadAllText(FILENAME);
XElement element = XElement.Parse("<Root xmlns:y=\"www.mynamespace.com\"></Root>");
element.Add(input);
}
}
}
​

How can i import MULTIPLE XmlNodes from one document to another?

i am trying to add XmlNodes from one XmlDocument to another as a new node.
My main issue is that i can import only the First or Last child of the document but not the ones in between. all of the nodes i am trying to import have the same layout but i cant seem to create any iteration for importing them all since i can only select either the FirstChild or LastChild - Please note this is also across 2 forms.
I am new to Xml but do not want to re-write my whole Xml Document over again in an XDocument, any help would be greatly appreciated, Thanks.
Code Below:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Xml;
using System.Xml.Serialization;
using System.IO;
namespace XmlCreator
{
public partial class Form_Member : Form
{
string MPlayID, MNick, MName, MMail, MICQ, MRemark;
public static XmlDocument xmlMembers = null;
static XmlNode rootNode = null;
public Form_Member()
{
InitializeComponent();
}
private void btnAdd_Click(object sender, EventArgs e)
{
if (xmlMembers != null)
{
XmlNode member = xmlMembers.CreateElement("member");
XmlAttribute attID = xmlMembers.CreateAttribute("id");
attID.Value = MPlayID;
member.Attributes.Append(attID);
XmlAttribute attNick = xmlMembers.CreateAttribute("nick");
attNick.Value = MNick;
member.Attributes.Append(attNick);
rootNode.AppendChild(member);
XmlNode MNameNode = xmlMembers.CreateElement("name");
MNameNode.InnerText = MName;
member.AppendChild(MNameNode);
XmlNode MMailNode = xmlMembers.CreateElement("email");
MMailNode.InnerText = MMail;
member.AppendChild(MMailNode);
XmlNode MICQNode = xmlMembers.CreateElement("icq");
MICQNode.InnerText = MICQ;
member.AppendChild(MICQNode);
XmlNode MRemarkNode = xmlMembers.CreateElement("remark");
MRemarkNode.InnerText = MRemark;
member.AppendChild(MRemarkNode);
xmlMembers.Save("memberXML.xml");
clearTextFields();
}
}
private void Form_Member_Load(object sender, EventArgs e)
{
xmlMembers = new XmlDocument();
rootNode = xmlMembers.CreateElement("members");
xmlMembers.AppendChild(rootNode);
}
}
}
This is the form of which the Xml file i am trying to import is being created from, i am trying to import this to another form with the following code on the form i am trying to import it to.
code below:
XmlNode memberNode = xmlSquad.ImportNode(Form_Member.xmlMembers.DocumentElement.FirstChild, true);
xmlSquad.DocumentElement.AppendChild(memberNode);
To conclude, it is importing the FirstChild, however, i am making more than 1 memberNode in the xmlMembers.xml file from the other form which i can't find a way of copying over.
Any help will be appreciated, Thank you.
You need the following extension method:
public static class XmlNodeExtensions
{
/// <summary>
/// Copy all child XmlNodes from the source to the destination.
/// </summary>
/// <param name="source">Copy children FROM this XmlNode</param>
/// <param name="destination">Copy children TO this XmlNode</param>
public static void CopyChildren(this XmlNode source, XmlNode destination)
{
if (source == null || destination == null)
throw new ArgumentNullException();
var doc = destination.OwnerDocument;
if (doc == null)
throw new InvalidOperationException("null document");
// Clone the array to prevent infinite loops when the two nodes are from the same document.
foreach (var child in source.ChildNodes.Cast<XmlNode>().ToArray())
{
var copy = doc.ImportNode(child, true);
destination.AppendChild(copy);
}
}
}
You can then use it like:
Form_Member.xmlMembers.DocumentElement.CopyChildren(xmlSquad.DocumentElement);

C# XmlDocument for grabbing API specific data?

I am trying to grab the specific value of an attribute in:
http://data.alexa.com/data?cli=10&dat=snbamz&url=bing.com
<SD>
<POPULARITY URL="bing.com/" TEXT="16" SOURCE="panel"/>
<REACH RANK="16"/>
<RANK DELTA="-7"/>
<COUNTRY CODE="US" NAME="United States" RANK="9"/>
</SD>
</ALEXA>
I want to grab the value of
I have the current Console Code for this:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
string url = "http://data.alexa.com/data?cli=10&dat=snbamz&url=bing.com";
XmlDocument xmldoc = new XmlDocument();
xmldoc.Load(url);
XmlNode root = xmldoc.SelectSingleNode("//#RANK");
//XmlNamespaceManager xnm1 = new XmlNamespaceManager(xmldoc.NameTable);
//XmlNodeList nList1 = xmldoc.SelectNodes("//#RANK", xnm1);
Console.WriteLine(root.ToString());
Console.ReadLine();
}
}
}
But when I run it, I receive the following message in return:
System.Xml.XmlAttribute
What am I doing wrong?
Try changing:
Console.WriteLine(root.ToString());
to:
Console.WriteLine(root.Value);
Hope that helps.

Append Xml a given number of times

I am appending to an existing xml file: The code is below: I am using C# .net 4.5 VS 2012 and creating a WPF application.
How could I append this say 30 times and only change D100 attribute number to 2,3,4,5 etc?
The other values are the same!
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Xml;
namespace AppendX
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Button_Click_1(object sender, RoutedEventArgs e)
{
XmlDocument doc = new XmlDocument();
doc.Load("C:\\Temp.xml");
XmlNamespaceManager namespaces = new XmlNamespaceManager(doc.NameTable);
namespaces.AddNamespace("flp", "http://www.w3.org/2001/flp");
XmlNode nextNode = doc.SelectSingleNode("/flp:Tab/flp:Designs", namespaces);
XmlElement D100 = doc.CreateElement("flp", "D100", "http://www.w3.org/2001/flp");
D100.SetAttribute("Number", "2");
XmlElement Code = doc.CreateElement("flp", "Code", "http://www.w3.org/2001/flp");
Code.InnerText = "B";
D100.AppendChild(Code);
XmlElement Documented = doc.CreateElement("flp", "Documented", "http://www.w3.org/2001/flp");
Documented.InnerText = "false";
D100.AppendChild(Documented);
nextNode.AppendChild(D100);
doc.Save("test1.xml");
}
}
}
Here is the sample xml I am using, sorry I meant to put this up!
<flp:Tab xmlns:flp="http://www.w3.org/2001/flp" Title="Testing">
<flp:Form Number="0" id="1005" />
<flp:Rev Time="2013-01-21T15:08:00">
<flp:Author Name="Brad" Aid="15" />
</flp:Rev>
<flp:Designs Id="D100">
<flp:D100 Number="1">
<flp:Code>A</flp:Code>
<flp:Documented>true</flp:Documented>
</flp:D100>
</flp:Designs>
</flp:Tab>
Create a separate private function that would handle the creation of the document element, given the parameters. ex:
private xmlelement dothework(string param1, string param2){
'do all necessary work to set up the element in here and then return it
}
I would separate the work like this, create a different function for each section of work, so that eventually you can just loop through and append each to the document.

Categories