How to add nodes with the same name in a loop? - c#

I'm trying to create the following XML file:
<Clientes>
<Cliente>
<Name>sfsdfsd</Name>
<Phone>
</Phone>
<Matriculas>
<Matricula>
<Nr>567856786</Nr>
<Marca>86786</Marca>
<Modelo>8678678</Modelo>
</Matricula>
<Matricula>
<Nr>u56u5u</Nr>
<Marca>4564b5</Marca>
<Modelo>b456b</Modelo>
</Matricula>
</Matriculas>
</Cliente>
</Clientes>
I have several clientes stored in a List and each of them may have more then one Matricula, stored in a List
i have the following code:
foreach (Cliente c in cli)
{
XmlNode xCliente = xDoc.CreateElement("Cliente");
XmlNode xName = xDoc.CreateElement("Name");
XmlNode xPhone = xDoc.CreateElement("Phone");
XmlNode xMatriculas = xDoc.CreateElement("Matriculas");
XmlNode xMatricula = xDoc.CreateElement("Matricula");
XmlNode xNr = xDoc.CreateElement("Nr");
XmlNode xMarca = xDoc.CreateElement("Marca");
XmlNode xModelo = xDoc.CreateElement("Modelo");
xName.InnerText = c.Name;
xPhone.InnerText = c.Phone;
xCliente.AppendChild(xName);
xCliente.AppendChild(xPhone);
foreach (Matricula m in c.matricula)
{
xNr.InnerText = m.nr;
xMarca.InnerText = m.marca;
xModelo.InnerText = m.modelo;
xMatricula.AppendChild(xNr);
xMatricula.AppendChild(xMarca);
xMatricula.AppendChild(xModelo);
xMatriculas.AppendChild(xMatricula);
}
xCliente.AppendChild(xMatriculas);
xDoc.DocumentElement.AppendChild(xCliente);
}
i can add several Cliente to the root, but only the last Matricula in Matriculas is added.

Move
XmlNode xMatricula = xDoc.CreateElement("Matricula");
XmlNode xNr = xDoc.CreateElement("Nr");
XmlNode xMarca = xDoc.CreateElement("Marca");
XmlNode xModelo = xDoc.CreateElement("Modelo");
inside the inner for loop.
You are reusing the exact same node, you need to create a new node every time you want a new node in your document.

Related

How to check if an XML node exists in the children of another node?

I want to add an XmlNode to another XmlNode if it doesn't contain this node (the comparison should be based on the node name and its contents)
System.Xml.XmlDocument doc;
...
XmlNode newNode = doc.CreateElement(name);
newNode.InnerXml = something
XmlNode parentNode = doc.GetElementsByTagName(parentName);
if (parentNode.???? (newNode))
{
parentNode.AppendChild(newNode);
}
How can I check this existence? parentNode.ChildNodes doesn't have a Contain method.
I think this will do the trick:
private void doSomething()
{
XmlDocument doc = new XmlDocument();
XmlNode newNode = doc.CreateElement("name");
newNode.InnerXml = "something";
XmlNode parentNode = doc.GetElementsByTagName("parentName")[0];
// I just stuck an index on end of above line...
// Note that GetElementsByTagName returns an XmlNodeList
int huh = 0;
foreach (XmlNode n in parentNode.ChildNodes)
{
// If I understood you correctly, you want these checks?
if (n.InnerXml == newNode.InnerXml && n.Name == newNode.Name) huh++;
}
if (huh == 0) parentNode.AppendChild(newNode);
}
You could do this using LINQ to XML making use of the XNode.DeepEquals method to compare your child nodes for equality. An example might look like this - the duplicateChild will not be added but newChild will be:
var doc = new XDocument(
new XElement("parent",
new XElement("child", 1)));
var parent = doc.Descendants("parent").Single();
var duplicateChild = new XElement("child", 1);
var newChild = new XElement("child", 2);
if (!parent.Elements().Any(e => XNode.DeepEquals(e, duplicateChild)))
{
parent.Add(duplicateChild);
}
if (!parent.Elements().Any(e => XNode.DeepEquals(e, newChild)))
{
parent.Add(newChild);
}
A demo here: https://dotnetfiddle.net/1t4Q1b

Efficient way to export database tables to XML file in c#.net

I have a sqlite database which has 7 tables. I need to export them to an XML file in c#.net.
When doing so, i have used 7 loops nested to access the data of 7 Datatables to maintain the dependencies of columns. but while i run it, my machine becomes very slow. it generates XML file, but the generated XML changes after some time. it seems, in every iteration , it generates one XML and replace it by new one. my codes are following :
public XMLSerializer(String filepath,ROOT root)
{
XmlDocument doc = new XmlDocument();
XmlNode rootNode, aNode, pNode, eNode, mNode, plNode;
// Create a procesing instruction.
XmlProcessingInstruction newPI;
String PItext = "type='text/xsl' href='root.xsl'";
newPI = doc.CreateProcessingInstruction("xml-stylesheet", PItext);
// Add the processing instruction node to the document.
doc.AppendChild(newPI);
rootNode = doc.CreateElement("root");
doc.AppendChild(rootNode);
plNode = doc.CreateElement("pl");
rootNode.AppendChild(plNode);
eNode = doc.CreateElement("e");
rootNode.AppendChild(eNode);
mNode = doc.CreateElement("m");
rootNode.AppendChild(mNode);
aNode = doc.CreateElement("a");
rootNode.AppendChild(aNode);
DataTable plDT = root.Getpl();
foreach (DataRow pRow in plDT.Rows)
{
XmlNode plNode = doc.CreateElement("p");
XmlNode pIDNode = doc.CreateElement("id");
XmlNode pteNode = doc.CreateElement("te");
XmlNode fNode = doc.CreateElement("fs");
plNode.AppendChild(pIDNode);
plNode.AppendChild(pteNode);
plNode.AppendChild(fNode);
plNode.AppendChild(plNode);
pIDNode.InnerText = pRow["id"].ToString();
pteNode.InnerText = root.Getpte(pRow["id"].ToString());
DataTable fmdt = root.GetFml(pRow["id"].ToString());
foreach (DataRow fmRow in fmdt.Rows)
{
XmlNode fsNode = doc.CreateElement("fm");
XmlNode fmIDNode = doc.CreateElement("id");
XmlNode fmpNode = doc.CreateElement("p");
XmlNode eNode = doc.CreateElement("e");
fsNode.AppendChild(fmIDNode);
fsNode.AppendChild(fmpNode);
fsNode.AppendChild(eNode);
plNode.AppendChild(fsNode);
fmIDNode.InnerText = fmRow["id"].ToString();
fmpNode.InnerText = pRow["id"].ToString();
DataTable eDT = root.Gete();
foreach (DataRow eRow in eDT.Rows)
{
XmlNode eNode = doc.CreateElement("e");
XmlNode eIDNode = doc.CreateElement("id");
XmlNode eDanNode = doc.CreateElement("dan");
XmlNode mNode = doc.CreateElement("m");
eNode.AppendChild(eIDNode);
eNode.AppendChild(edanNode);
//eNode.AppendChild(eNode);
fsNode.AppendChild(eNode);
eIDNode.InnerText = eRow["id"].ToString();
edanNode.InnerText = root.Getedan(eRow["id"].ToString());
DataTable mDT = root.Getm();
foreach (DataRow mRow in mDT.Rows)
{
XmlNode mNode = doc.CreateElement("m");
XmlNode mIDNode = doc.CreateElement("id");
XmlNode meNode = doc.CreateElement("e");
mNode.AppendChild(mIDNode);
mNode.AppendChild(meNode);
eNode.AppendChild(mNode);
mIDNode.InnerText = mRow["id"].ToString();
meNode.InnerText = root.Getme(mRow["id"].ToString());
DataTable aDT = root.Geta();
foreach (DataRow aRow in aDT.Rows)
{
XmlNode aNode = doc.CreateElement("a");
XmlNode AssIDNode = doc.CreateElement("id");
XmlNode AssNaNode = doc.CreateElement("na");
XmlNode pinNode = doc.CreateElement("pin");
aNode.AppendChild(AssIDNode);
aNode.AppendChild(AssNaNode);
aNode.AppendChild(pinNode);
AssIDNode.InnerText = aRow["id"].ToString();
AssNaNode.InnerText = aRow["na"].ToString();
mNode.AppendChild(aNode);
DataTable piDT = root.Getp(aRow["id"].ToString());
foreach (DataRow piRow in piDT.Rows)
{
XmlNode pInNode = doc.CreateElement("pIn");
XmlNode pInIDNode = doc.CreateElement("id");
XmlNode pInaNode = doc.CreateElement("a");
XmlNode pInpNode = doc.CreateElement("p");
XmlNode pInFminNode = doc.CreateElement("fmin");
pInNode.AppendChild(pInIDNode);
pInNode.AppendChild(pInaNode);
pInNode.AppendChild(pInpNode);
pInNode.AppendChild(pInFminNode);
aNode.AppendChild(pInNode);
pInIDNode.InnerText = piRow["id"].ToString();
pInaNode.InnerText = aRow["id"].ToString();
pInpNode.InnerText = pRow["id"].ToString();
DataTable fmiDT = root.GetFmin(piRow["id"].ToString());
foreach (DataRow fmiRow in fmiDT.Rows)
{
XmlNode fmInNode = doc.CreateElement("fmIn");
XmlNode fmInIDNode = doc.CreateElement("id");
XmlNode fmInpInNode = doc.CreateElement("pIn");
XmlNode fmInFmNode = doc.CreateElement("fm");
XmlNode fmIneNode = doc.CreateElement("e");
XmlNode fmInmNode = doc.CreateElement("m");
fmInNode.AppendChild(fmInIDNode);
fmInNode.AppendChild(fmInpInNode);
fmInNode.AppendChild(fmInFmNode);
fmInNode.AppendChild(fmIneNode);
fmInNode.AppendChild(fmInmNode);
pInNode.AppendChild(fmInNode);
fmInIDNode.InnerText = fmiRow["id"].ToString();
fmInpInNode.InnerText = piRow["id"].ToString();
fmInFmNode.InnerText = fmRow["id"].ToString();
fmIneNode.InnerText = eRow["id"].ToString();
fmInmNode.InnerText = mRow["id"].ToString();
}
}
}
}
}
}
}
doc.Save(filepath);
}
}
}
i think my way of coding is not efficient. could anyone please show me any better approach of accessing the datatables ?
you can simply use DataTable.WriteXml() :
YourDataTable.WriteXml(strfilepath);
or
YourDataSet.WrteXml(strfilepath);

How to get xml element values using XmlNodeList in c#

I need to store the element values which are inside the nodes "member" . I have tried the following code but I can't achieve it. How to get the values. Any help would be appreciated
XML:
<ListInventorySupplyResponse xmlns="http://mws.amazonaws.com/FulfillmentInventory/2010-10-01/">
<ListInventorySupplyResult>
<InventorySupplyList>
<member>
<SellerSKU>043859634910</SellerSKU>
<FNSKU>X000IA4045</FNSKU>
<ASIN>B005YV4DJO</ASIN>
<Condition>NewItem</Condition>
<TotalSupplyQuantity>7</TotalSupplyQuantity>
<InStockSupplyQuantity>7</InStockSupplyQuantity>
<EarliestAvailability>
<TimepointType>Immediately</TimepointType>
</EarliestAvailability>
<SupplyDetail>
</SupplyDetail>
</member>
</InventorySupplyList>
</ListInventorySupplyResult>
<ResponseMetadata>
<RequestId>58c9f4f4-6f60-496a-8d71-8fe99ce301c9</RequestId>
</ResponseMetadata>
</ListInventorySupplyResponse>
C# Code:
string a = Convert.ToString(oInventorySupplyRes.ToXML());
XmlDocument oXdoc = new XmlDocument();
oXdoc.LoadXml(a);
XmlNodeList oInventorySupplyListxml = oXdoc.SelectNodes("//member");
foreach (XmlNode itmXml in oInventorySupplyListxml)
{
// var cond = itmXml.InnerXml.ToString();
var asinVal = itmXml.SelectSingleNode("ASIN").Value;
var TotalSupplyQuantityVal = itmXml.SelectSingleNode("TotalSupplyQuantity").Value;
}
ResultView : "Enumeration yielded no results" and count = 0;
Edit 1:
string a = Convert.ToString(oInventorySupplyRes.ToXML());
var status = oInventorySupplyResult.InventorySupplyList;
XmlDocument oXdoc = new XmlDocument();
var doc = XDocument.Parse(a);
var r = doc.Descendants("member")
.Select(member => new
{
ASIN = member.Element("ASIN").Value,
TotalSupplyQuantity = member.Element("TotalSupplyQuantity").Value
});
private string mStrXMLStk = Application.StartupPath + "\\Path.xml";
private System.Xml.XmlDocument mXDoc = new XmlDocument();
mXDoc.Load(mStrXMLStk);
XmlNode XNode = mXDoc.SelectSingleNode("/ListInventorySupplyResult/InventorySupplyList/member");
if (XNode != null)
{
int IntChildCount = XNode.ChildNodes.Count;
for (int IntI = 1; IntI <= IntChildCount ; IntI++)
{
string LocalName = XNode.ChildNodes[IntI].LocalName;
XmlNode Node = mXDoc.SelectSingleNode("/Response/" + LocalName);
// Store Value in Array assign value by "Node.InnerText"
}
}
Try This Code. Its Worked
try using this xpath
string xPath ="ListInventorySupplyResponse/ListInventorySupplyResult
/InventorySupplyList/member"
XmlNodeList oInventorySupplyListxml = oXdoc.SelectNodes(xpath);
when you do "//member", then, the code is trying to look for element named member from the root level, which is not present at the root level, rather it is nested beneath few layers.
I think this will help you..
string a = Convert.ToString(oInventorySupplyRes.ToXML());
XmlDocument oXdoc = new XmlDocument();
oXdoc.LoadXml(a);
XmlNodeList fromselectors;
XmlNodeList toselectors;
XmlElement root = oXdoc.DocumentElement;
fromselectors = root.SelectNodes("ListInventorySupplyResult/InventorySupplyList/member/ASIN");
toselectors = root.SelectNodes("ListInventorySupplyResult/InventorySupplyList/member/TotalSupplyQuantity");
foreach (XmlNode m in fromselectors)
{
you will have value in `m.InnerXml` use it whereever you want..
}
foreach (XmlNode n in toselectors)
{
you will have value in `n.InnerXml` use it whereever you want..
}

Renaming xmlnodes using c# dynamically

I am using the below code to rename the xmlnode name dynamically. It's looping though the xml just fine, but it does not change the node name. Please help me to do this.
Sample XML doucment
- <NewDataSet>
- <Table5>
<FLD_ID>62</FLD_ID>
<FLD_DATE>2013-03-12</FLD_DATE>
<FLD_MOD_DATE>2013-04-05</FLD_MOD_DATE>
<FLD_DESC>New Creation</FLD_DESC>
</Table5>
- </NewDataSet>
Needed XML DOCUMENT
- <rows>
- <row>
<cell>62</cell>
<cell>2013-03-12</cell>
<cell>2013-04-05</cell>
<cell>New Creation</cell>
</row>
- </rows>
My code is here
XmlNode PackageListNode = hst_doc.SelectSingleNode("NewDataSet");
XmlNodeList PackageNodeList = PackageListNode.SelectNodes("Table5");
foreach (XmlNode node in PackageNodeList)
{
node.Name.Replace("Table5", "row");
foreach (XmlNode ls in node)
{
ls.Name.Replace(ls.Name, "cell");
}
}
As you can't replace element names in an XmlDocument...
...a replacement approach for your specific situation:
string srcXML = "<NewDataSet><Table5><FLD_ID>62</FLD_ID><FLD_DATE>2013-03-12</FLD_DATE><FLD_MOD_DATE>2013-04-05</FLD_MOD_DATE><FLD_DESC>New Creation</FLD_DESC></Table5></NewDataSet>";
var doc = new XmlDocument();
doc.LoadXml(srcXML);
XmlNode oldRoot = doc.SelectSingleNode("NewDataSet");
XmlNode newRoot = doc.CreateElement("rows");
doc.ReplaceChild(newRoot, oldRoot);
foreach (XmlNode childNode in oldRoot.ChildNodes)
{
newRoot.AppendChild(childNode.CloneNode(true));
}
XmlNodeList PackageNodeList = newRoot.SelectNodes("Table5");
foreach (XmlNode node in PackageNodeList)
{
var newNode = doc.CreateElement("row");
newRoot.ReplaceChild(newNode, node);
foreach (XmlNode childNode in node.ChildNodes)
{
var clonedChildNode = childNode.CloneNode(true);
newNode.AppendChild(clonedChildNode);
var newChildNode = doc.CreateElement("cell");
newNode.ReplaceChild(newChildNode, clonedChildNode);
foreach (XmlNode childChildNode in clonedChildNode.ChildNodes)
{
newChildNode.AppendChild(childChildNode.CloneNode(true));
}
}
}
Debug.Print(doc.OuterXml);
Embrace LINQ, embrace it!
// load the document from a file
var doc = XDocument.Load(xmlPath);
var root = doc.Root;
// replace the root element with a new element
root.ReplaceWith(
// create a new element with
// the name "rows" with new children
new XElement("rows",
// replace all child elements of
// the root with new elements
root.Elements().Select(table =>
// replace the current element with a new element
// with the name "row" with the new children
new XElement("row",
// replace all child elements of the
// current element with new elements
table.Elements().Select(field =>
// replace the current element with a new element
// with the name "cell" with the same value
new XElement("cell",
(string)field
)
)
)
)
)
);
// save the document back to the file
doc.Save(xmlPath);
String.Replace returns a new string, so of course one would love to:
node.Name = node.Name.Replace("Table5", "row");
which might as well be
node.Name = "row";
however, if you look at the documentation it says that XmlNode.Name is purely a 'getter' and not a 'setter', so maybe you'll need to create whole new nodes to replace them, it depends on the actual implementation, since XmlNode is an abstract class.
for (int i = 0; i < PackageNodeList.Count; ++i) XmlNode node in PackageNodeList)
{
XmlNode replacementNode = new XmlNode("row");
foreach (XmlNode ls in node)
{
XmlNode newCell = new XmlNode("cell");
newCell.Value = ls.Value;
replacementNode.AppendChild(newCell);
}
PackageNodeList[i] = replacementNode
PackageNodeList[i].ParentNode.ReplaceChild(PackageNodeList[i], replacementNode);
}

Deleting XML using a selected Xpath and a for loop

I currently have the following code:
XPathNodeIterator theNodes = theNav.Select(theXPath.ToString());
while (theNodes.MoveNext())
{
//some attempts i though were close
//theNodes.RemoveChild(theNodes.Current.OuterXml);
//theNodes.Current.DeleteSelf();
}
I have set xpath to what I want to return in xml and I want to delete everything that is looped. I have tried a few ways of deleting the information but it does't like my syntax. I found an example on Microsoft support: http://support.microsoft.com/kb/317666 but I would like to use this while instead of a for each.
Any comments or questions are appreciated.
Why not to use XDocument?
var xmlText = "<Elements><Element1 /><Element2 /></Elements>";
var document = XDocument.Parse(xmlText);
var element = document.XPathSelectElement("Elements/Element1");
element.Remove();
var result = document.ToString();
result will be <Elements><Element2 /></Elements>.
Or:
var document = XDocument.Load(fileName);
var element = document.XPathSelectElement("Elements/Element1");
element.Remove();
document.Savel(fileName);
[Edit] For .NET 2, you can use XmlDocument:
XmlDocument document = new XmlDocument();
document.Load(fileName);
XmlNode node = document.SelectSingleNode("Elements/Element1");
node.ParentNode.RemoveChild(node);
document.Save(fileName);
[EDIT]
If you need to remove all child elements and attributes:
XmlNode node = document.SelectSingleNode("Elements");
node.RemoveAll();
If you need to keep attributes, but delete elements:
XmlNode node = document.SelectSingleNode("Elements");
foreach (XmlNode childNode in node.ChildNodes)
node.RemoveChild(childNode);
string nodeXPath = "your x path";
XmlDocument document = new XmlDocument();
document.Load(/*your file path*/);
XmlNode node = document.SelectSingleNode(nodeXPath);
node.RemoveAll();
XmlNode parentnode = node.ParentNode;
parentnode.RemoveChild(node);
document.Save("File Path");
You can use XmlDocument:
string nodeXPath = "your x path";
XmlDocument document = new XmlDocument();
document.Load(/*your file path*/);//or document.LoadXml(...
XmlNode node = document.SelectSingleNode(nodeXPath);
if (node.HasChildNodes)
{
//note that you can use node.RemoveAll(); it will remove all child nodes, but it will also remove all node' attributes.
for (int childNodeIndex = 0; childNodeIndex < node.ChildNodes.Count; childNodeIndex++)
{
node.RemoveChild(node.ChildNodes[childNodeIndex]);
}
}
document.Save("your file path"));

Categories

Resources