Reputation: 851
I am trying to extract some SQL data to XML from a Microsoft Dynamics environment, I am currently using LINQ To XML in C# to read and write to my XML files. One piece of data I need is from a view called SECURITYSUBROLE. Looking at the structure of this view shows that there is a column also named SECURITYSUBROLE. My normal method of extraction has given me this XML.
<SECURITYSUBROLE>
<SECURITYROLE>886301</SECURITYROLE>
<SECURITYSUBROLE>886317</SECURITYSUBROLE>
<VALIDFROM>1900-01-01T00:00:00-06:00</VALIDFROM>
<VALIDFROMTZID>0</VALIDFROMTZID>
<VALIDTO>1900-01-01T00:00:00-06:00</VALIDTO>
<VALIDTOTZID>0</VALIDTOTZID>
<RECVERSION>1</RECVERSION>
<RECID>886317</RECID>
</SECURITYSUBROLE>
When I try to import this data later on, I am getting errors because the parent XML node has the same name as a child node. Here is a snippet of the import method:
XmlReaderSettings settings = new XmlReaderSettings();
settings.CheckCharacters = false;
XmlReader reader = XmlReader.Create(path, settings);
reader.MoveToContent();
int count = 1;
List<XElement> xmlSubset = new List<XElement>();
while (reader.ReadToFollowing(xmlTag))
{
if (count % 1000 == 0)
{
xmlSubset.Add(XElement.Load(reader.ReadSubtree()));
XDocument xmlTemp = new XDocument(new XElement(xmlTag));
foreach (XElement elem in xmlSubset)
{
xmlTemp.Root.Add(elem);
}
xmlSubset = new List<XElement>();
ImportTableByName(connectionString, tableName, xmlTemp);
count = 1;
}
else
{
xmlSubset.Add(XElement.Load(reader.ReadSubtree()));
count++;
}
}
}
It's currently failing on the XmlReader.ReadToFollowing, where it doesn't know where to go next because of the name confusion. So my question has two parts:
1) Is there some better way to be extracting this data other than to XML?
2) Is there a way through LINQ To XML that I can somehow differentiate between the parent and child nodes named exactly the same?
Upvotes: 1
Views: 950
Reputation: 11945
To get the elements (in your case) for SECURITYSUBROLE
you can check to see if the element's have children:
XElement root = XElement.Load(path);
var subroles = root.Descendants("SECURITYSUBROLE") // all subroles
.Where(x => !x.HasElements); // only subroles without children
Upvotes: 2
Reputation: 4395
I'm going to suggest a different approach:
1) VS2013 (possibly earlier versions too) has a function to create a class from an XML source. So get one of your XML files and copy the content to your clipboard. Then in a new class file Edit
--> Paste Special
--> Paste XML as Classes
2) Look into XmlSerialization
which will allow you to convert an XML file into an in memory object with a strongly typed class.
XmlSerializer s = new XmlSerializer(yourNewClassTYPE);
TextReader r = new StreamReader(XmlFileLocation);
var dataFromYourXmlAsAStronglyTypedClass = (yourNewlyClassTYPE) s.Deserialize(r);
r.Close();
Upvotes: 0