I'm trying to insert a XML tag in an existing xml-file. To insert an XML-Tag in C# is not really a problem, but my Problem is, that i need the new beginning-tag and the ending-tag on a certain place in that file ... can anybody help me ...
here an Example:
this is the xml-file before:
<?xml version="1.0" standalone="yes"?>
<DocumentElement>
<Item>
<ItemID>2711</ItemID>
<ItemTypeID>P</ItemTypeID>
<ColorID>1</ColorID>
</Item>
<Item>
<ItemID>64566</ItemID>
<ItemTypeID>P</ItemTypeID>
<ColorID>3</ColorID>
</Item>
</DocumentElement>
... this should be the new XML-file -> with the new tag "Inventory":
<?xml version="1.0" standalone="yes"?>
<DocumentElement>
<Inventory>
<Item>
<ItemID>2711</ItemID>
<ItemTypeID>P</ItemTypeID>
<ColorID>1</ColorID>
</Item>
<Item>
<ItemID>64566</ItemID>
<ItemTypeID>P</ItemTypeID>
<ColorID>3</ColorID>
</Item>
</Inventory>
</DocumentElement>
can anybody help me?
You can wrap the existing Items in a new XElement then replace the nodes on the original document:
XDocument doc = XDocument.Parse("<DocumentElement><Item><ItemID>2711</ItemID><ItemTypeID>P</ItemTypeID><ColorID>1</ColorID></Item><Item><ItemID>64566</ItemID><ItemTypeID>P</ItemTypeID><ColorID>3</ColorID></Item></DocumentElement>");
var items = doc.Descendants("Item");
XElement inventory = new XElement("Inventory");
inventory.Add(items);
doc.Root.ReplaceNodes(inventory);
//now you can save the XDocument to a file or whatever
Creates this:
<DocumentElement>
<Inventory>
<Item>
<ItemID>2711</ItemID>
<ItemTypeID>P</ItemTypeID>
<ColorID>1</ColorID>
</Item>
<Item>
<ItemID>64566</ItemID>
<ItemTypeID>P</ItemTypeID>
<ColorID>3</ColorID>
</Item>
</Inventory>
</DocumentElement>
If you have LINQPad you can run this script: http://share.linqpad.net/7c636x.linq
You can try this
var doc = XDocument.Load(file);
var characters = doc.Descendants("DocumentElement").FirstOrDefault();
if (characters != null)
{
XElement xe = new XElement("Inventory");
characters.Add(xe);
var oColl = doc.Descendants("Item");
xe.Add(oColl);
}
doc.Save(file);
Related
I'm trying to insert an xml node with another child xml node in an existing xmldocument in C#.
I've got an XML doc that looks like so:
<?xml version="1.0" encoding="utf-16"?>
<DictionarySerializer>
<item>
<key>statusCode</key>
<value>0</value>
</item>
<item>
<key>statusSeverity</key>
<value>INFO</value>
</item>
<item>
<key>statusMessage</key>
<value>Status OK</value>
</item>
<item>
<key>MerchantAccountNumber</key>
<value>9999999999</value>
</item>
<item>
<key>ReconBatchID</key>
<value>420150418 1Q02144266965047801046AUTO04</value>
</item>
<item>
<key>PaymentGroupingCode</key>
<value>3</value>
</item>
<item>
<key>responsePaymentStatus</key>
<value>Completed</value>
</item>
<item>
<key>TxnAuthorizationTime</key>
<value>2015-04-18T09:14:41</value>
</item>
<item>
<key>TxnAuthorizationStamp</key>
<value>1429348481</value>
</item>
<item>
<key>ClientTransID</key>
<value>aidjl79f</value>
</item>
</DictionarySerializer>
and I need to insert another node with a node and node at the bottom.
I have this so far:
XmlDocument xmlCustomValues = new XmlDocument();
xmlCustomValues.LoadXml(OldCustomValues);
XmlNode NodeItem = xmlCustomValues.SelectSingleNode("DictionarySerializer");
XmlNode NodeNewItem = xmlCustomValues.CreateNode(XmlNodeType.Element, "item", null);
XmlNode NodeNewKey = NodeNewItem.??????
but not sure how to create a node under NodeNewItem (there's no "CreateNode" method). Never done this before (obviously) and the syntax does not make sense to me.
here's an answer that worked (test code for XML doc above)
string OldCustomValues = this.txtInput.Text;
XmlDocument xmlCustomValues = new XmlDocument();
xmlCustomValues.LoadXml(OldCustomValues);
XmlNode NodeItem = xmlCustomValues.SelectSingleNode("DictionarySerializer");
XmlNode NodeNewItem = xmlCustomValues.CreateNode(XmlNodeType.Element, "item", null);
NodeItem.AppendChild(NodeNewItem);
XmlNode NodeNewKey = xmlCustomValues.CreateNode(XmlNodeType.Element, "key", null);
NodeNewKey.InnerText = "MyKey";
XmlNode NodeNewValue = xmlCustomValues.CreateNode(XmlNodeType.Element, "value", null);
NodeNewValue.InnerText = "MyValue";
NodeNewItem.AppendChild(NodeNewKey);
NodeNewItem.AppendChild(NodeNewValue);
this.txtOutput.Text = xmlCustomValues.OuterXml;
You have already created the node, u just need to append the node to the root
NodeItem.AppendChild(NodeNewItem);
This question already has an answer here:
How to sort XML in LINQ C# by an attribute value? Also MVC
(1 answer)
Closed 7 years ago.
I have the following xml file.(sample) .. I need to sort the 'invoice' nodes by the attribute 'InvcDate'. Is this even possible in Linq? Any help would be much appreciated.
I have been trying for some time however I don't have much experience with xml and and am a relative newcomer to programming, so I would be very grateful for any help at all.
<?xml version="1.0" encoding="utf-8"?>
<Server>
<Name>AlignServer</Name>
<Params>
<marketNo>MT</marketNo>
<dateFrom>2015-01-06</dateFrom>
<dateTo>2015-01-09</dateTo>
<Sales>
<invoices>
<invoice>
<header>
<InvoiceNum>22947</InvoiceNum>
<InvcDate>2015/01/07-110104</InvcDate>
</header>
<item>
<SKU>6595456987453</SKU>
<Qty>-1</Qty>
</item>
</invoice>
<invoice>
<header>
<InvoiceNum>23056</InvoiceNum>
<InvcDate>2015/01/08-020627</InvcDate>
</header>
<item>
<SKU>9845256242255</SKU>
<Qty>-1</Qty>
</item>
</invoice>
<invoice>
<header>
<InvoiceNum>22899</InvoiceNum>
<InvcDate>2015/01/06-094505</InvcDate>
</header>
<item>
<SKU>5454256565452</SKU>
<Qty>-1</Qty>
</item>
<item>
<SKU>11111165454130</SKU>
<Qty>4</Qty>
</item>
</invoice>
</invoices>
</Sales>
</Params>
</Server>
I have tried
XElement root = XElement.Load("C:\\xmlsort\\test.xml");
XElement[] sortedTables = root.Elements("invoices").OrderBy(t => (Datetime)t.Element("invdate")).ToArray();
root.ReplaceAll(sortedTables);
root.Save("C:\\xmlsort\\test.xml");
What I have done so far - with suggestion from #ec8or and seems to work but still open to suggestions:
XElement root = XElement.Load("C:\\xmlsort\\test.xml");
var invoices = from p in root.Descendants("invoice")
orderby DateTime.ParseExact(p.Element("header").Element("InvcDate").Value, "yyyy/MM/dd-hhmmss", CultureInfo.InvariantCulture)
select p;
XElement[] sortedTables = invoices.ToArray();
root.ReplaceAll(sortedTables);
root.Save("C:\\xmlsort\\output.xml");
Read you XML in a XElement:
XElement element = XElement.Load("doc.xml");
Query you XML data:
var invoices = from p in element.Descendants ("invoice")
orderby DateTime.ParseExact(p.Element("header").Element("InvcDate").Value, "yyyy/MM/dd-hhmmss", CultureInfo.InvariantCulture)
select p;
Print it to the console:
foreach (var invoice in invoices) {
Console.WriteLine (invoice.ToString ());
}
EDIT
Answer to your question in comments.
XDocument doc = XDocument.Load ("data.xml");
Select all parent node:
var baseElement = doc.XPathSelectElement ("/Server/Params/Sales/invoices");
sort the inner nodes:
var sortedElements = baseElement.Elements ()
.OrderBy (e => (DateTime)e.XPathSelectElement("header/InvoiceNum"))
.ToList ();
replace the current content with the sortet content:
baseElement.ReplaceAll (sortedElements);
doc.Save ("out.xml");
I have an XML file, which I like to parse and get the value in a string type array. I know there are XMLSerialization namespace and other things. But what I am trying to achieve is getting the value in a string array. It may be obtained using Foreach loop or for loop.
For example, here is my XML file:
<?xml version="1.0" encoding="utf-8" ?>
<channel>
<title>Social Media</title>
<item>
<title>Facebook</title>
<link>http://www.facebook.com/</link>
</item>
<item>
<title>Twitter</title>
<link>http://www.twitter.com/</link>
</item>
<item>
<title>Google+</title>
<link>http://plus.google.com/</link>
</item>
</channel>
Now, I have two string type array as variable into a C# file.
For example:
public string[] WebsiteName;
public string[] Urls;
Now, I want to get all the values of WebsiteName into the WebsiteName array and website links into the Urls array.
Is there any way to do it? If yes, please show it to me. It will be very helpful.
Here is an example to get website names and links using LINQ:
var xml = #"<?xml version=""1.0"" encoding=""utf-8"" ?>
<channel>
<title>Social Media</title>
<item>
<title>Facebook</title>
<link>http://www.facebook.com/</link>
</item>
<item>
<title>Twitter</title>
<link>http://www.twitter.com/</link>
</item>
<item>
<title>Google+</title>
<link>http://plus.google.com/</link>
</item>
</channel>";
var doc = XDocument.Parse(xml);
WebsiteName = doc.Descendants("title").Select(o => o.Value).ToArray();
Urls = doc.Descendants("link").Select(o => o.Value).ToArray();
XDocument.Parse(xml): create XDocument from string. If you want the source is file instead of string then you can use XDocument.Load("path_to_the_xml_file").
doc.Descendants("title"): will get all tags named "title", then
.Select(o => o.Value): will get the string between the opening and closing tag, aka the value
var doc = XDocument.Parse(xml);
var WebsiteName = doc.Descendants("title").Select(o => o.Value).ToArray();
ListBox.ItemsSource = WebsiteName;
And you get content written in listbox.
I've figured out how to append nodes to my rss document in the right structyre. I now need to sort it in the pubDate order and then output to screen. Looking at the examples online, I've found lots of XDocument and Linq stuff but nothing with XmlDocument. Scratching my head whether to scrap what code I have and work out how to do it in XDocument with advice from here or continue with XMLDocument and figure out a way to sort.
With XMLDocument I've got the code working exactly as I want, just need my feed to be sorted in pubDate order when it spits it out to the screen. So I think I will stick with this for the timebeing. I've found this article http://support.microsoft.com/kb/555060 and an xslt someone posted in Stack Overflow, but I dont know how to call the "XmlHelperFunctions" from my code. Is XSLT the easiest option I have, or is there something easier out there?
This is my code:
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(rssFeed.ToString());
XmlNodeList nl = xmlDoc.SelectNodes("/rss/channel/item");
foreach (XmlNode xn in nl)
{
string title = xn["title"].InnerText;
string link = xn["link"].InnerText;
string desc = xn["description"].InnerText;
string auth = xn["author"].InnerText;
string pdate = xn["pubDate"].InnerText;
XmlElement itemnode = xmlDoc.CreateElement("item");
itemnode.InnerXml = "<title></title><link></link><description></description><author></author><pubDate></pubDate>";
itemnode["title"].InnerText = title;
itemnode["link"].InnerText = link;
itemnode["description"].InnerText = desc;
itemnode["author"].InnerText = auth;
itemnode["pubDate"].InnerText = pdate;
xmlDoc.DocumentElement.SelectNodes("/rss/channel")[0].AppendChild(itemnode);
}
// Output to screen
xmlDoc.Save(Response.Output);
my rss feed
<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.0">
<channel>
<title>My RSS Feed</title>
<link>http://www.mylink.aspx</link>
<description>
</description>
<item>
<title>Top marks</title>
<link>http://www.mymarks.aspx</link>
<description>
<p>description field here</p>
</description>
<author>Viv</author>
<pubDate>Thu, 16 Aug 2012 12:10:54 GMT</pubDate>
</item>
<item>
<title>Costa Coffee</title>
<link>http://www.Costa.aspx</link>
<description>
<p>Costa Coffee have special offers.</p>
</description>
<author>Mike</author>
<pubDate>Thu, 23 Aug 2012 15:55:53 GMT</pubDate>
</item>
<item>
<title>Celebrate success</title>
<link>http://www.Celebrate.aspx</link>
<description>
<p>Lets all celebrate </p>
</description>
<author>Viv</author>
<pubDate>Thu, 22 Aug 2012 09:10:21 GMT</pubDate>
</item>
</channel>
</rss>
You can do this fairly quickly and painlessly using Linq to XML.
If you parse your XML using XElement.Parse(...) you can then use OrderBy or OrderByDescending functions and alter the content pretty easily.
Here is a simplified example:
XElement element = XElement.Parse(#"
<rss>
<channel>
<item title='something' pubDate='22/11/2012'/>
<item title='something2' pubDate='24/03/2012'/>
<item title='something3' pubDate='10/02/2010'/>
<item title='something4' pubDate='22/01/2011'/>
</channel>
</rss>");
var elements = element.Element("channel")
.Elements("item")
.OrderBy<XElement, DateTime>(e => DateTime.ParseExact(e.Attribute("pubDate").Value, "dd/MM/yyyy", null))
.Select(e => new XElement("item",
new XElement("title", e.Attribute("title").Value),
new XElement("pubDate", e.Attribute("pubDate").Value))); // Do transform here.
element.Element("channel").ReplaceAll(elements);
Console.Write(element.ToString());
The XML is not going to be the same as yours, but hopefully it gives you an idea of what you could do. You can just specify XElement and XAttribute objects as content for your new XML, this outputs the following:
<rss>
<channel>
<item>
<title>something3</title>
<pubDate>10/02/2010</pubDate>
</item>
<item>
<title>something4</title>
<pubDate>22/01/2011</pubDate>
</item>
<item>
<title>something2</title>
<pubDate>24/03/2012</pubDate>
</item>
<item>
<title>something</title>
<pubDate>22/11/2012</pubDate>
</item>
</channel>
</rss>
I hope this is useful.
The XML dataset file after I add it to a DataSet looks like this:
<?xml version="1.0" standalone="yes"?>
<root>
<Email></Email>
<FirstName></FirstName>
<LastName></LastName>
<Addresses>
<item>
<Address1></Address1>
</item>
<item>
<Address1></Address1>
</item>
</Addresses>
<Friends>
<item>
<Name></Name>
</item>
<item>
<Name></Name>
</item>
</Friends>
</root>
I am having issues accessing the Address1 field or the Name field. I can loop through the Addresses or Friends tables but that doesn't help me since the data I want is wrapped one more level down.
I tried this:
foreach (DataRow ar in ds.Tables["Addresses"].Rows)
{
DataRow[] orderDetails = ar.GetChildRows("item");
}
But no success.
Help appreciated.
Thanks
using linq to XML
public static XDocument GetXDocument()
{
XDocument mydata = XDocument.Parse("<?xml version=\"1.0\" standalone=\"yes\"?><root><Email></Email><FirstName></FirstName><LastName></LastName><Addresses><item><Address1>TestData</Address1></item><item><Address1></Address1></item></Addresses> <Friends> <item> <Name></Name> </item><item><Name></Name></item></Friends></root>");
return mydata;
}
this gets the data as a XDocument and this is how you deal with the data
public void OutputAddress()
{
XDocument data = xmlData.GetXDocument();
string Expected = "TestData";
var result = from
addesses in data.Element("root").Elements("Addresses")
where
addesses.Element("item").Element("Address1").Value != string.Empty
select addesses.Element("item").Element("Address1").Value;
foreach (string address1 in result)
{
Console.Write(address1);
}
}
I suggest you use an object wrapper whenever working with XML. This is very eashy to do, I suggest you have a look at this blog:
http://www.picnet.com.au/blogs/Guido/post/2009/09/10/XML-Settings-Files-No-more-webconfig.aspx
Which is aimed at settings XML files however it still applies here.
Thanks
Guido Tapia