Adding XML element to existing XML element in xml file C# - c#

Please i'm trying to insert data into xml, this is the current format of my xml file after inserting data
<?xml version="1.0" encoding="utf-8"?>
<ApplicationData>
<Minutes>
</Minutes>
<Minute MinuteId="6" Title="Project6" Date="6" Time="Project6" Location="6" MinuteDocumentFile="Project6" />
<Minute MinuteId="6" Title="Project6" Date="6" Time="Project6" Location="6" MinuteDocumentFile="Project6" />
</ApplicationData>
using this code below
XmlTextReader _xmlTextReader = new XmlTextReader(config.XMLPath);
XmlDocument _xmlDocument = new XmlDocument();
_xmlDocument.Load(_xmlTextReader);
//Note: Close the reader object to release the xml file. Else while saving you will get an error that it is
//being used by another process.
_xmlTextReader.Close();
XmlElement _minutesElement = _xmlDocument.CreateElement("Minute");
_minutesElement.SetAttribute("MinuteId", "6");
_minutesElement.SetAttribute("Title", "Project6");
_minutesElement.SetAttribute("Date", "6");
_minutesElement.SetAttribute("Time", "Project6");
_minutesElement.SetAttribute("Location", "6");
_minutesElement.SetAttribute("MinuteDocumentFile", "Project6");
_xmlDocument.DocumentElement.AppendChild(_minutesElement);
_xmlDocument.Save(config.XMLPath);
That above code works fine, but my challenge now is, i'm trying to achieve the current format of xml shown below
<?xml version="1.0" encoding="utf-8"?>
<ApplicationData>
<Minutes>
<Minute MinuteId="6" Title="Project6" Date="6" Time="Project6" Location="6" MinuteDocumentFile="Project6" />
<Minute MinuteId="6" Title="Project6" Date="6" Time="Project6" Location="6" MinuteDocumentFile="Project6" />
</Minutes>
</ApplicationData>
I want to store the created "Minute" XmlElement inside the "Minutes" Element, not outside it.
Thanks..

The line
_xmlDocument.DocumentElement.AppendChild(_minutesElement);
is just appending your new _minutesElement to the end of the tree. You need to tell it which element you want it to belong to.
Changing it instead to be:
_xmlDocument.DocumentElement["Minutes"].AppendChild(_minutesElement);
Gives:
<?xml version="1.0" encoding="utf-8"?>
<ApplicationData>
<Minutes>
<Minute MinuteId="6" Title="Project6" Date="6" Time="Project6" Location="6" MinuteDocumentFile="Project6" />
</Minutes>
</ApplicationData>

var doc = XElement.Load(config.XMLPath);
var target = doc.Descendants("Minutes").First();
target.Add(new XElement("Minute", new XAttribute("MinuteId", 6), new ...));
doc.Save(config.XMLPath);

Related

Passing XML multi level data as parameter and using in stored procedure

I have XML format data which I will pass from a .net application.
In the SQL Server stored procedure, this data is passed in as a XML parameter. I want to read and save the data in the required tables, say TblOrder and TblItem.
In XML, there will be multiple orders. Each order contains one or several items accordingly.
Structure on which operation need to be implemented:
<?xml version="1.0" encoding="UTF-8"?>
<Orders>
<Order>
<B2>B2**ABIJ**0000884443**PP</B2>
<CreateBy null="true" />
<CreateDate>/Date(1485150414358)/</CreateDate>
<CurrencyId>1</CurrencyId>
<CustomerId>13</CustomerId>
<DeliveryAddress>LIBERTY PRESS LLC</DeliveryAddress>
<DeliveryCity>SPRINGVILLE UT 84663</DeliveryCity>
<DeliveryCityId>0</DeliveryCityId>
<DeliveryDate>/Date(1478750400000)/</DeliveryDate>
<DeliveryId>14</DeliveryId>
<DeliveryState>UT</DeliveryState>
<DeliveryStateId>16</DeliveryStateId>
<DeliveryType>Delivery</DeliveryType>
<EquipmentId>4</EquipmentId>
<Items>
<Item>
<CSA>false</CSA>
<CTPAT>false</CTPAT>
<CommodityItem>General Freight</CommodityItem>
<CommodityItemId>0</CommodityItemId>
<CustCommodityItem null="true" />
<FAST>false</FAST>
<Hazmat>false</Hazmat>
<Height null="true" />
<IsActive>false</IsActive>
<ItemId>0</ItemId>
<ItemName>Item A</ItemName>
<Length null="true" />
<Make null="true" />
<Mass null="true" />
<MassUnit null="true" />
<Model null="true" />
<OrderId>0</OrderId>
<PIP>false</PIP>
<PilotCar>false</PilotCar>
<ReeferTemp null="true" />
<Tarp>false</Tarp>
<TrailerType null="true" />
<TruckType null="true" />
<VIN null="true" />
<Width null="true" />
<Year null="true" />
</Item>
</Items>
<L11>L11*SYL884443*BM</L11>
<LastUpdate>/Date(1485150414358)/</LastUpdate>
</Order>
<Order>
...
<Items>
<Item>
...
</Item>
</Order>
</Orders>
Steps I want to achieve are:
Read XML parameter from the stored procedure, which is passed from the .net application.
Loop through the XML and save data in the TblOrder and TblItem tables
Going through the article follows :
Pass-XML-parameter-to-Stored-Procedure
How to loop and parse xml parameter in sql server stored procedure
I got the Idea to access very first level (in my case Order of Orders).
Moving forward having issue accessing the second level which will be again a collection (in my case Item of Items of Order).
Thanks in advance for your support
You have two approaches:
You can pass the XML as-is into a Stored Procedure and do all the hard work in T-SQL
You can shredd the XML within C#, fill appropriate data objects and use classical data storage.
From your question I take, that you'd prefer to pass this into a stored procedure as XML parameter. There are some things to know:
C# uses 16-bit-unicode internally and so does SQL Server's XML. But you will not be able to cast this unicode string to XML as long as there is encoding="UTF-8" included... You might pass this as VARCHAR(MAX) (not NVARCHAR(MAX)!), but this could lead you in troubles if there are sepcial characters involved. Best was, to cut the first line (the <?xml ...?> declaration) away completely.
Your XML is not created correctly. Is this under you control? If you include null="true" (there's no need for normally!), you should do this with the xsi-namespace. And date/time values within XML should be ISO8601. Your values (like /Date(1485150414358)/) are no format SQL Server will be able to cast directly...
Nevertheless I see multi <Order>-elements and multi <Item>-elements. You could read them as follows:
DECLARE #xml XML=
N'<Orders>
<Order>
<B2>B2**ABIJ**0000884443**PP</B2>
<CreateBy null="true" />
<CreateDate>/Date(1485150414358)/</CreateDate>
<CurrencyId>1</CurrencyId>
<CustomerId>13</CustomerId>
<DeliveryAddress>LIBERTY PRESS LLC</DeliveryAddress>
<DeliveryCity>SPRINGVILLE UT 84663</DeliveryCity>
<DeliveryCityId>0</DeliveryCityId>
<DeliveryDate>/Date(1478750400000)/</DeliveryDate>
<DeliveryId>14</DeliveryId>
<DeliveryState>UT</DeliveryState>
<DeliveryStateId>16</DeliveryStateId>
<DeliveryType>Delivery</DeliveryType>
<EquipmentId>4</EquipmentId>
<Items>
<Item>
<CSA>false</CSA>
<CTPAT>false</CTPAT>
<CommodityItem>General Freight</CommodityItem>
<CommodityItemId>0</CommodityItemId>
<CustCommodityItem null="true" />
<FAST>false</FAST>
<Hazmat>false</Hazmat>
<Height null="true" />
<IsActive>false</IsActive>
<ItemId>0</ItemId>
<ItemName>Item A</ItemName>
<Length null="true" />
<Make null="true" />
<Mass null="true" />
<MassUnit null="true" />
<Model null="true" />
<OrderId>0</OrderId>
<PIP>false</PIP>
<PilotCar>false</PilotCar>
<ReeferTemp null="true" />
<Tarp>false</Tarp>
<TrailerType null="true" />
<TruckType null="true" />
<VIN null="true" />
<Width null="true" />
<Year null="true" />
</Item>
</Items>
<L11>L11*SYL884443*BM</L11>
<LastUpdate>/Date(1485150414358)/</LastUpdate>
</Order>
</Orders>';
--the query
SELECT --elements of Order
o.value(N'(B2)[1]',N'nvarchar(max)') AS B2
--very strange date-format...
,o.value(N'(CreateDate)[1]',N'nvarchar(max)') AS CreateDate
--typed INT
,o.value(N'(CurrencyId)[1]',N'int') AS CurrencyId
--more like this
--elements of Item
,i.value(N'(CSA)[1]',N'nvarchar(max)') AS CSA
--There's no need for *null="true"*
--Query the "/text()" and the empty element will be NULL
,CASE WHEN i.value(N'(CustCommodityItem/#null)[1]',N'nvarchar(max)')=N'true' THEN NULL ELSE i.value(N'(CustCommodityItem)[1]',N'nvarchar(max)') END AS CustCommodityItem_complicated
,i.value(N'(CustCommodityItem)[1]',N'nvarchar(max)') AS CustCommodityItem_empty
,i.value(N'(CustCommodityItem/text())[1]',N'nvarchar(max)') AS CustCommodityItem_null
FROM #xml.nodes(N'/Orders/Order') AS A(o)
OUTER APPLY o.nodes(N'Items/Item') AS B(i)

Merging issue in two xml documents using XDocument

The existing XML file(test.xml) content is as under
<manifest xmlns:imsmd="http://ltsc.ieee.org/xsd/LOM">
<resources>
<resource>
<file href="default.xml">
<metadata>
<imsmd:lom />
</metadata>
</file>
</resource>
</resources>
</manifest>
What I need is to add new node so that the final output resembles:
<manifest xmlns:imsmd="http://ltsc.ieee.org/xsd/LOM">
<resources>
<resource>
<file href="default.xml">
<metadata>
<imsmd:lom />
</metadata>
</file>
<file href="testimg.png">
<metadata>
<imsmd:lom />
</metadata>
</file>
</resource>
</resources>
</manifest>
My try so far (though not entirely correct is as under)
XNamespace ns = #"http://ltsc.ieee.org/xsd/LOM";
XNamespace lomns = ":lom";
var doc = XDocument.Load(#"D:\test.xml");
var result = new XDocument(
new XElement(ns + "manifest",
new XElement("file", new XAttribute("href", "testimg.png"),
new XElement("metadata", new XElement(lomns + "imsmd"))
)
)
);
//merge
doc.Root.Add(result.Root.Elements());
whose output is
<manifest xmlns:imsmd="http://ltsc.ieee.org/xsd/LOM">
<resources>
<resource>
<file href="default.xml">
<metadata>
<imsmd:lom />
</metadata>
</file>
</resource>
</resources>
<file href="testimg.png">
<metadata>
<imsmd xmlns=":lom" />
</metadata>
</file>
</manifest>
Code is adding new element to the root, but as per your required output you mentioned a new element(file) should be resource.
Locate the element resource in your xml and then add the element.
doc.Descendants("resource")
.ElementAt(0)
.Add(new XElement("file", new XAttribute("href", "testimg.png"),
new XElement("metadata", new XElement(doc.Root.GetNamespaceOfPrefix("imsmd")+ "lom"))));
Output:
<manifest xmlns:imsmd="http://ltsc.ieee.org/xsd/LOM">
<resources>
<resource>
<file href="default.xml">
<metadata>
<imsmd:lom />
</metadata>
</file>
<file href="testimg.png">
<metadata>
<imsmd:lom />
</metadata>
</file>
</resource>
</resources>
</manifest>
Check this Demo

Delete multiple XML nodes in C# using Linq

I'm trying to remove multiple nodes that a particular element(path) contains a value but I'm receiving a System.NullReferenceException any help where I'm going wrong would I'be much appreciated.
My xml looks like this:
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<ApplicationData Version="12.5.1" RootPath="FireFox-FILES">
<RegistrySystem>
<DIR Operation="+" Path="C:\Temp\Microsoft\MediaPlayer\ShimInclusionList" />
<DIR Operation="+" Path="C:\Temp\MediaPlayer\ShimInclusionList\MM.EXE" />
<DIR Operation="+" Path="C:\Temp\MediaPlayer\ShimInclusionList\plugin-container.exe" />
<DIR Operation="+" Path="C:\Temp\Microsoft\MediaPlayer">
<ENTRY Name="" Value="43.0.4" Type="1" />
<ENTRY Name="CurrentVersion" Value="43.0.4 (x86 en-GB)" Type="1" />
</DIR>
<DIR Operation="+" Path="C:\Program Files\Microsoft\MediaPlayer\ShimInclusionList\plugin-container.exe" />
<DIR Operation="+" Path="C:\Program Files\Microsoft\MediaPlayer\ShimInclusionList2\plugin.exe" />
<DIR Operation="+" Path="C:\Program Files\Microsoft\MediaPlayer\ShimInclusionList2\container.exe" />
<DIR Operation="+" Path="C:\Program Files\Microsoft\MediaPlayer\ShimInclusionList4">
<ENTRY Name="" Value="43.0.4" Type="1" />
<ENTRY Name="CurrentVersion" Value="43.0.4 (x86 en-GB)" Type="1" />
</DIR>
</RegistrySystem>
</ApplicationData>
My code looks like this:
XDocument xdoc = XDocument.Load(XmlFile);
foreach (var node in xdoc.Descendants("DIR").Where(status => status.Attribute("Path").Value.Contains(#"C:\Temp\")))
{
node.Remove();
}
xdoc.Save(XmlFile);
I'm not sure where I'm going wrong.
I'm not sure why you're getting the exception, but I strongly suspect it's because you're modifying the document while you're querying it.
If you change your code to use a ToList() call to get the list of nodes to remove, that doesn't throw:
foreach (var node in xdoc.Descendants("DIR")
.Where(status => status.Attribute("Path").Value.Contains(#"C:\Temp\"))
.ToList())
{
node.Remove();
}
However, that's not the best way. The best approach is to use the Remove(this IEnumerable<XElement>) extension method:
xdoc.Descendants("DIR")
.Where(status => status.Attribute("Path").Value.Contains(#"C:\Temp\"))
.Remove();
No need for a foreach loop at all. Now to make it robust in the face of DIR elements without a Path attribute, you can cast to string instead:
xdoc.Descendants("DIR")
.Where(status => ((string) status.Attribute("Path") ?? "").Contains(#"C:\Temp\"))
.Remove();

How can i remove Nodes of Manifest-File created with Mage.exe/MageUI.exe without getting trouble with the namespace?

In the Last few Days i tried to .Remove(); some Nodes in a Manifest-File , to specify the Problem i tried to delete the Populated-Files in a Manifest-File with a C# programm.
If you don't know exactly what a Populated file is i will explain it as good as i can:
A Populated File is a File (example: "Populated-File.txt.deploy") wich one you need for you're Manifest-File, because without Populated-Files your Application won't do that much. When you press the "Populate"-Button in the MageUI.exe or you set the Option "-FromDirectory" in the Mage.exe you will add Nodes in the Manifest-File, they are called <dependency dependencyType="install"></dependency> and <file></file>. In these Nodes are Informations about the Populated-Files(example: name="Populated-File.txt.deploy" size="123" location="..."and so on).
These Nodes are in the Manifest-File just like that:
Attention should be paid to the 2nd Node : <asmv1:assembly>, because that is default if the Manifest-File got created with MageUi.exe/ Mage.exe, there starts the Problem.
<?xml version="1.0" encoding="utf-8"?>
<asmv1:assembly xsi:schemaLocation="urn:schemas-microsoft-com:asm.v1 assembly.adaptive.xsd" manifestVersion="1.0" xmlns:asmv1="urn:schemas-microsoft-com:asm.v1" xmlns="urn:schemas-microsoft-com:asm.v2" xmlns:asmv2="urn:schemas-microsoft-com:asm.v2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:co.v1="urn:schemas-microsoft-com:clickonce.v1" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3" xmlns:dsig="http://www.w3.org/2000/09/xmldsig#" xmlns:co.v2="urn:schemas-microsoft-com:clickonce.v2">
<asmv1:assemblyIdentity name="Example.exe" />
<description asmv2:iconFile="Example.ico" xmlns="urn:schemas-microsoft-com:asm.v1" />
<dependency>
<dependentAssembly dependencyType="install" size="123">
</dependentAssembly>
</dependency>
<file name="PopulatedFile.dll.deploy" size="123">
</file>
</asmv1:assembly>
After a while I got it, with some help from this Forum.
//does currently only delete the "<dependency></dependency>"-Node
xml.Descendants().Where(x => x.Name.LocalName == "dependentAssembly" && (string)x.Attribute("dependencyType") == "install").Select(x => x.Parent).Remove();
xml.Save(filePath);
So far so good, but as i added .Remove(); for the <file></file>-Node that the Code looked like that:
xml.Descendants().Where(x => x.Name.LocalName == "dependentAssembly" && (string)x.Attribute("dependencyType") == "install").Select(x => x.Parent).Remove();
xml.Descendants().Where(x => x.Name == "file").Remove();
xml.Save(filePath);
I noticed that the Manifest-File has added, infront of almost every Node, asmv2: and the <dependency>-Nodes got deleted. It would be better when <dependency>/<file>-Nodes get deleted and there would be any asmv2.
Just like that:
<?xml version="1.0" encoding="utf-8"?>
<asmv1:assembly xsi:schemaLocation="urn:schemas-microsoft-com:asm.v1 assembly.adaptive.xsd" manifestVersion="1.0" xmlns:asmv1="urn:schemas-microsoft-com:asm.v1" xmlns="urn:schemas-microsoft-com:asm.v2" xmlns:asmv2="urn:schemas-microsoft-com:asm.v2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:co.v1="urn:schemas-microsoft-com:clickonce.v1" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3" xmlns:dsig="http://www.w3.org/2000/09/xmldsig#" xmlns:co.v2="urn:schemas-microsoft-com:clickonce.v2">
<asmv1:assemblyIdentity name="Example.exe" />
<description asmv2:iconFile="Example.ico" xmlns="urn:schemas-microsoft-com:asm.v1" />
<asmv2:file name="PopulatedFile.dll.deploy" size="123">
</asmv2:file>
</asmv1:assembly>
The consiquence is that the File is not openable anymore with MageUi.exe.
So i started to research also on this Forum, and got as answer its the Namespace.
xmlns:asmv2="urn:schemas-microsoft-com:asm.v2"
So finally:
My question is How could i solve this?
As always: You can edit this so it gets more specific or even more correnct (maybe i didn't explained the Populate-Files right)
Please correct me in any way but be constructive :)
Okay, it looks like LINQ to XML is getting confused because the namespace is declared twice in the root element - once as the default namespace, and once with an alias of asmv2. The simplest solution is just to remove that attribute.
To be honest, MageUI should cope with it anyway - it's representing the right data. Yet another program that doesn't look at the XML properly, apparently. (Sigh...)
I'd also look for descendants with the right name (in the right namespace) rather than looking for a particular LocalName. For example:
var doc = XDocument.Load("test.xml");
doc.Root.Attribute(XNamespace.Xmlns + "asmv2").Remove();
XNamespace ns = "urn:schemas-microsoft-com:asm.v2";
doc.Descendants(ns + "dependentAssembly")
.Where(x => (string)x.Attribute("dependencyType") == "install")
.Select(x => x.Parent)
.Remove();
doc.Descendants(ns + "file").Remove();
doc.Save("test2.xml");
Output (reformatted a little):
<?xml version="1.0" encoding="utf-8"?>
<asmv1:assembly
xsi:schemaLocation="urn:schemas-microsoft-com:asm.v1 assembly.adaptive.xsd"
manifestVersion="1.0"
xmlns:asmv1="urn:schemas-microsoft-com:asm.v1"
xmlns="urn:schemas-microsoft-com:asm.v2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:co.v1="urn:schemas-microsoft-com:clickonce.v1"
xmlns:asmv3="urn:schemas-microsoft-com:asm.v3"
xmlns:dsig="http://www.w3.org/2000/09/xmldsig#"
xmlns:co.v2="urn:schemas-microsoft-com:clickonce.v2">
<asmv1:assemblyIdentity name="Example.exe" />
<description p8:iconFile="Example.ico"
xmlns="urn:schemas-microsoft-com:asm.v1"
xmlns:p8="urn:schemas-microsoft-com:asm.v2" />
</asmv1:assembly>

exporting XmlDocument to excel

I have a XmlDocument in which i have hierarchical data and i want to export this data to excel. Please help me to get out of this.
I have tried to read this data into a dataset but it is not working for me.
Please send xml sample for more information.
Your code loads xml into dataset, so,
if your xml doesn't exported from DataSet, you could use LinqToXml.
for example:
xml:
<?xml version="1.0" encoding="utf-8" ?>
<rss version="2.0">
<channel>
<title>Business Logic Toolkit for .NET</title>
<link>http://www.bltoolkit.net</link>
<description />
<lastBuildDate>2009-01-11</lastBuildDate>
<item>
<title>Version 3.1 released</title>
<link>http://www.bltoolkit.net/Download.htm</link>
<description>See <a href="http://www.bltoolkit.net/Download.htm">change log</a></description>
<pubDate>2009-01-11</pubDate>
</item>
<item>
<title>Version 3.0 released</title>
<link>http://www.bltoolkit.net/Download.htm</link>
<description>See <a href="http://www.bltoolkit.net/Download.htm">change log</a></description>
<pubDate>2008-05-21</pubDate>
</item>
<item>
<title>New examples</title>
<link>http://www.bltoolkit.net/Doc/</link>
<description>See the following <a href="http://www.bltoolkit.net/Doc/">link</a></description>
<pubDate>2008-05-10</pubDate>
</item>
</channel>
</rss>
this code get all rss items title
var path = #"D:\rss.xml";
var doc = XDocument.Load(path);
rssTitles = doc.Root.Descendants("item").Elements("title").Select(el => el.Value);
results:
Version 3.1 released
Version 3.0 released
New examples
<Roles>
<BalanceSheets RoleURL="http://fluor.com/role/BalanceSheets" RoleDefination="0020 - CONDENSED CONSOLIDATED BALANCE SHEET">
<Taxonomys>
<StatementOfFinancialPositionAbstract TaxonomyPresentationId="StatementOfFinancialPositionAbstract">
<StatementLineItems TaxonomyPresentationId="StatementOfFinancialPositionAbstract">
<LiabilitiesAndStockholdersEquityAbstract TaxonomyPresentationId="StatementLineItems">
<CommitmentsAndContingencies TaxonomyPresentationId="LiabilitiesAndStockholdersEquityAbstract" />
<OtherLiabilitiesNoncurrent TaxonomyPresentationId="LiabilitiesAndStockholdersEquityAbstract" />
<NonRecourseProjectFinanceDebtNoncurrent TaxonomyPresentationId="LiabilitiesAndStockholdersEquityAbstract" />
<LongTermDebtNoncurrent TaxonomyPresentationId="LiabilitiesAndStockholdersEquityAbstract" />
<LiabilitiesCurrentAbstract TaxonomyPresentationId="LiabilitiesAndStockholdersEquityAbstract">
<BillingsInExcessOfCost TaxonomyPresentationId="LiabilitiesCurrentAbstract" />
<LiabilitiesCurrent TaxonomyPresentationId="LiabilitiesCurrentAbstract" />
<AccountsPayable TaxonomyPresentationId="LiabilitiesCurrentAbstract" />
<BridgeLoan TaxonomyPresentationId="LiabilitiesCurrentAbstract" />
<NonRecourseProjectFinanceDebtCurrent TaxonomyPresentationId="LiabilitiesCurrentAbstract" />
<EmployeeRelatedLiabilities TaxonomyPresentationId="LiabilitiesCurrentAbstract" />
<OtherAccruedLiabilities TaxonomyPresentationId="LiabilitiesCurrentAbstract" />
<ConvertibleDebtCurrent TaxonomyPresentationId="LiabilitiesCurrentAbstract" />
</LiabilitiesCurrentAbstract>
</LiabilitiesAndStockholdersEquityAbstract>
</StatementLineItems>
</StatementOfFinancialPositionAbstract>
</Taxonomys>
</BalanceSheets>
</Roles>

Categories