I have generated xmldocument by this code with C#,
protected XDocument generateXML()
{
XDocument xdoc = new XDocument(
new XDeclaration("1.0", "utf-8", "yes"),
new XElement("Invoices",
new XElement("Invoice",
new XElement("InvoiceNumber", "s10838652")
.......
return xdoc;
}
and in another method I have:
public override void RunWintrackConnector()
{
XDocument xml = generateXML();
.....
Then I would like to put data in each XML node: (instead of s10838652 I would like to assign (string.Concat(bill.invoice, bill.num);) to the InvoiceNumber node.)
I have the right part but not sure how get access to each node of xml:
xmlnode(for example InvoiceNumber) = Win2.IntegrationXML.XMLMisc.DirtyData.getStringValue(string.Concat(bill.invoice, bill.num));
xml
.Elements("Invoices")
.Elements("Invoice")
.Elements("InvoiceNumber")
.First()
.Value = string.Concat(bill.invoice, bill.num);
edit - to go over all your invoices:
foreach(var invoice in xml.Elements("Invoices").Elements("Invoice"))
{
invoice.Element("InvoiceNumber").Value = "asdf";
}
If you are familiar with XPath, this is equivalent to selecting all invoices with "Invoices/Invoice".
You can use XElement or XDocument to write the values you need.
var valueToInsert = Win2.IntegrationXML.XMLMisc.DirtyData
.getStringValue(string.Concat(bill.invoice, bill.num));
XDocument xml = generateXML();
xml.Element("Invoices")
.Elements("Invoice").First() //this First is just an example
.Element("InvoiceNumber")
.Value = valueToInsert;
Element() Returns the first found child node, and Elements() gets a list of all child nodes with that node name. Find out your pattern of how nodes are nested and you should be all set.
As a side note, you can do the above with a XDocument variable, but I prefer to keep everything as XElement for the added Linq compatibility.
Related
I am work on some innerxml of an XML document.
I have to concat several parts.
I have this:
<TRANFSERT><GOOD></GOOD></TRANSFERT>
I want to insert another part, <GOOD></GOOD>, before </TRANSFERT>.
I tried this:
int pos = xmldoc.indexOf("</GOOD>");
StringBuilder sb = new StringBuilder(xmlFinal);
sb.Append(xmlModifiee,pos,xmlModifiee.length);
xmlFinal = sb.ToString();
But it doesn't work.
How can I add a small part of XML in other XML?
You shouldn't interact with XML like with ordinary string.
Use provided System.Xml.XmlDocument or System.Xml.Linq.XDocument classes:
Ordinary XmlDocument single node selection and appending new element to it:
XmlDocument xmlDocument = new XmlDocument();
xmlDocument.Load("YourFile.xml");
XmlNode goodNode = xmlDocument.SelectSingleNode("TRANSFERT/GOOD");
XmlNode nodeToInsert = xmlDocument.CreateElement("INSERTEDNODE");
goodNode.AppendChild(nodeToInsert);
Ordinary XmlDocument iterating by nodes to find necessary (be aware for many-childed nodes) and add new child node to it:
XmlDocument xmlDocument = new XmlDocument();
xmlDocument.Load("YourFile.xml");
foreach (XmlNode rootNode in xmlDocument.ChildNodes)
{
if (rootNode.Name == "TRANSFERT")
{
foreach (XmlNode childNode in rootNode.ChildNodes)
{
if (childNode.Name == "GOOD")
{
XmlNode nodeToInsert = xmlDocument.CreateElement("INSERTEDNODE");
childNode.AppendChild(nodeToInsert);
}
}
}
}
Linq to XML variant:
XDocument xDoc = XDocument.Load("YourFIle.xml");
XElement rootElement = xDoc.Element("TRANSFERT");
XElement goodElement = rootElement.Element("GOOD");
goodElement.Add(new XElement("INSERTEDNODE"));
Simplified Linq to XML variant:
XDocument.Load("YourFIle.xml").Element("TRANSFERT").Element("GOOD").Add(new XElement("INSERTEDNODE"));
EDITED: answering the question, example was rewrited from changing InnerText values to Append/Add new child element to GOOD node.
StringBuilder.Append can only be used to add something to the end of the string. To add something inside the string, use StringBuilder.Insert like this:
sb.Insert(pos, xmlModifiee);
I got this function for simply get the inner text of my xml:
XmlDocument document = new XmlDocument();
document.Load("game.xml");
string content = document.SelectSingleNode("Game/Client-Version").InnerText;
(this is the xml file (due to complications with stackoverflow posted on pastebin)): http://pastebin.com/EEeFAJpC
And now I am exactly looking for the function above, just to write. Like
document.WriteSingleNode("Game/Client-Version", "texttowrite");
I did not find anything helping me out.
This should work
XmlElement x = document.SelectSingleNode("Game/Client-Version") as XmlElement;
x.InnerText = "texttowrite";
Create your own extension method:
public void WriteSingleNode(this XmlDocument document, string NodeName, string InnerText)
{
// Create a new element node.
XmlNode newElem = document.CreateNode("element", "pages", "");
newElem.InnerText = InnerText;
Console.WriteLine("Add the new element to the document...");
document.DocumentElement.AppendChild(newElem);
Console.WriteLine("Display the modified XML document...");
Console.WriteLine(document.OuterXml);
}
Having problems getting NodeList.SelectSingleNode() to work properly.
My XML looks like this:
<?xml version="1.0" encoding="ISO-8859-1" standalone="yes"?>
<inm:Results xmlns:inm="http://www.namespace.com/1.0">
<inm:Recordset setCount="18254">
<inm:Record setEntry="0">
<!-- snip -->
<inm:Image>fileName.jpg</inm:Image>
</inm:Record>
</inm:Recordset>
</inm:Results>
The data is a long series of <inm:Record> entries.
I open the doc and get create a NodeList object based on "inm:Record". This works great.
XmlDocument xdoc = new XmlDocument();
xdoc.Load(openFileDialog1.FileName);
XmlNodeList xRecord = xdoc.GetElementsByTagName("inm:Record");
I start looping through the NodeList using a for loop. Before I process a given entry, I want to check and see if the <inm:Image> is set. I thought it would be super easy just to do
string strImage = xRecord[i].SelectSingleNode("inm:Image").InnerText;
My thinking being, "For the XRecord that I'm on, go find the <inm:Image> value ...But this doesn't work as I get the exception saying that I need a XmlNameSpaceManager. So, I tried to set that up but could never get the syntax right.
Can someone show me how to use the correct XmlNameSpaceManager syntax in this case.
I've worked around the issue for now by looping through all of the childNodes for a given xRecord, and checking the tag once I loop around to it. I would like to check that value first to see if I need to loop over that <inm:Record> entry at all.
No need to loop through all the Record elements, just use XPath to specify the subset that you want:
XmlDocument xdoc = new XmlDocument();
xdoc.Load(openFileDialog1.FileName);
XmlNamespaceManager manager = new XmlNamespaceManager(xdoc.NameTable);
manager.AddNamespace("inm", "http://www.inmagic.com/webpublisher/query");
XmlNodeList nodes = xdoc.SelectNodes("/inm:Results/inm:Recordset/inm:Record[inm:Image != '']", manager);
Using the LINQ to XML libraries, here's an example for retrieving that said node's value:
XDocument doc = XDocument.Load(openFileDialog1.FileName);
List<XElement> docElements = doc.Elements().ToList();
XElement results = docElements.Elements().Where(
ele => ele.Name.LocalName == "Results").First();
XElement firstRecord = results.Elements().Where(
ele => ele.Name.LocalName == "Record").First();
XElement recordImage = firstRecord .Elements().Where(
ele => ele.Name.LocalName == "Image").First();
string imageName = recordImage.Value;
Also, by the way, using Hungarian notation for a type-checked language is overkill. You don't need to prepend string variables with str when it will always be a string.
XmlNamespaceManager nsMgr = new XmlNamespaceManager(xdoc.NameTable);
string strImage = xRecord[i].SelectSingleNode("inm:Image",nsMgr).InnerText;
Should do it.
Using this Xml library, you can get all the records that have an Image child element with this:
XElement root = XElement.Load(openFileDialog1.FileName);
XElement[] records = root.XPath("//Record[Image]").ToArray();
If you want to be sure that the Image child contains a value, it can be expressed like this:
XElement[] records = root.XPath("//Record[Image != '']").ToArray();
Using old way of doing via XmlDocument,
string xmlstring = "<root><profile><Name>John</Name><Age>23</Age></profile></root>";
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(xmlstring);
string childNodes = xmlDoc.SelectSingleNode("root/Profile").InnerXml;
// output of childNodes would be => "<Name>John</Name><Age>23</Age>";
what is the equivalent of doing the above execution in LinQ when you have XElement variable. I see XPathSelectElement method in XElement but it doesn't return the child nodes + Child nodes text. Any Ideas?
I wouldn't use XPath at all for this. I'd use:
XDocument doc = XDocument.Parse(xmlString);
var nodes = doc.Root
.Elements("profile")
.DescendantsAndSelf();
That give the profile nodes and all their descendants. It's not really clear what you're trying to do with the results, but if you can give more details I should be able to come up with the appropriate code.
I have XML stored in string variable:
<ItemMasterList><ItemMaster><fpartno>xxx</fpartno><frev>000</frev><fac>Default</fac></ItemMaster></ItemMasterList>
Here I want to change XML tag <ItemMasterList> to <Masterlist>. How can I do this?
System.Xml.XmlDocument and the associated classes in that same namespace will prove invaluable to you here.
XmlDocument doc = new XmlDocument();
doc.LoadXml(yourString);
XmlDocument docNew = new XmlDocument();
XmlElement newRoot = docNew.CreateElement("MasterList");
docNew.AppendChild(newRoot);
newRoot.InnerXml = doc.DocumentElement.InnerXml;
String xml = docNew.OuterXml;
I know i am a bit late, but just have to add this answer as no one seems to know about this.
XDocument doc = XDocument.Parse("<ItemMasterList><ItemMaster><fpartno>xxx</fpartno><frev>000</frev><fac>Default</fac></ItemMaster></ItemMasterList>");
doc.Root.Name = "MasterList";
Which returns the following:
<MasterList>
<ItemMaster>
<fpartno>xxx</fpartno>
<frev>000</frev>
<fac>Default</fac>
</ItemMaster>
</MasterList>
You can use LINQ to XML to parse the XML string, create a new root and add the child elements and attributes of the original root to the new root:
XDocument doc = XDocument.Parse("<ItemMasterList>...</ItemMasterList>");
XDocument result = new XDocument(
new XElement("Masterlist", doc.Root.Attributes(), doc.Root.Nodes()));
Using the XmlDocument way, you can do this as follows (and keep the tree intact):
XmlDocument oldDoc = new XmlDocument();
oldDoc.LoadXml("<ItemMasterList><ItemMaster><fpartno>xxx</fpartno><frev>000</frev><fac>Default</fac></ItemMaster></ItemMasterList>");
XmlNode node = oldDoc.SelectSingleNode("ItemMasterList");
XmlDocument newDoc = new XmlDocument();
XmlElement ele = newDoc.CreateElement("MasterList");
ele.InnerXml = node.InnerXml;
If you now use ele.OuterXml is will return: (you you just need the string, otherwise use XmlDocument.AppendChild(ele) and you will be able to use the XmlDocument object some more)
<MasterList>
<ItemMaster>
<fpartno>xxx</fpartno>
<frev>000</frev>
<fac>Default</fac>
</ItemMaster>
</MasterList>
As pointed by Will A, we can do it that way but for case where InnerXml equals the OuterXml the following solution will work out:
// Create a new Xml doc object with root node as "NewRootNode" and
// copy the inner content from old doc object using the LastChild.
XmlDocument docNew = new XmlDocument();
XmlElement newRoot = docNew.CreateElement("NewRootNode");
docNew.AppendChild(newRoot);
// The below line solves the InnerXml equals the OuterXml Problem
newRoot.InnerXml = oldDoc.LastChild.InnerXml;
string xmlText = docNew.OuterXml;