DataSet ReadXml ignores the attributes with prefix - c#

I have the following xml code which I want to read into a dataset:
<?xml version="1.0" standalone="yes"?>
<jlqn:Root xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:jlqn="http://jlqn/1.0">
<element xsi:type="jlqn:Processor" name="test1" processor="test">
<metadata name="Removed" value="False" />
<task id="6">
<entry id="8" entry="" />
</task>
</element>
<element xsi:type="jlqn:Processor" name="test1" processor="test" id="1">
<metadata name="Removed" value="True" />
<metadata name="Removed1" value="Removed1" />
</element>
<element xsi:type="jlqn:Processor" name="test1" processor="test" id="3">
<metadata name="Removed" value="False" />
<task id="45" name="">
<metadata />
<entry id="10" entry="">
<metadata />
</entry>
</task>
</element>
<element name="test" />
</jlqn:Root>
I use the following C# code
DataSet newTable = new DataSet();
newTable.ReadXml(#"F:\QVT\runtime-EclipseApplication\dr5\HJYU.jlqn");
But when I check the dataset , I notice all the attributes with prefix are not read ..such as this : xsi:type="jlqn:Processor"
what can I do ?

The XML references an namespace prefix "xsi", but it is not defined. Change the root element to:
<jlqn:Root xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:jlqn="http://jlqn/1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
Once I did this, I got the following tables and columns:
Root
Root_Id
version
element
element_Id
name
processor
id
Root_Id
metadata
name
value
element_Id
task
metadata
task_Id
id
name
element_Id
entry
metadata
id
entry
task_Id
That is the output from:
DataSet newTable = new DataSet();
newTable.ReadXml(#"XMLFile1.xml");
foreach(DataTable table in newTable.Tables)
{
Console.WriteLine(table.TableName);
foreach(DataColumn column in table.Columns)
{
Console.WriteLine(" " + column.ColumnName);
}
}

Related

How do I write fragmented xml file without root element?

I got fragmented xml file (document without root element/node):
<?xml version="1.0" standalone="no" ?>
<WndPos name="Login" l="703" r="1264" t="323" b="909" />
<WndPos name="Main" l="703" r="768" t="323" b="609" />
<LayerManager />
<ViewLayers name="Roof" roof="1">
<Layer level="1" visible="1" />
</ViewLayers>
<DirProfiles>
<ProfileInfo ProfileName="Control" DatabasePath="D:\Database\Control" />
</DirProfiles>
<DirHistory>
<ProfileInfo Use="Database" Path="D:\Database\Control" />
</DirHistory>
I am reading this file using the following:
string xmlPath = Environment.GetEnvironmentVariable("USERPROFILE") + "\\my.xml";
XmlReaderSettings settings = new XmlReaderSettings();
settings.ConformanceLevel = ConformanceLevel.Fragment;
XDocument doc = new XDocument(new XElement("root"));
XElement root = doc.Descendants().First();
using (StreamReader fs = new StreamReader(xmlPath))
using (XmlReader xr = XmlReader.Create(fs, settings))
{
while(xr.Read())
{
if (xr.NodeType == XmlNodeType.Element)
{
root.Add(XElement.Load(xr.ReadSubtree()));
}
}
}
Later on I change <DirProfiles>...</DirProfiles> section and getting the following data:
<?xml version="1.0" standalone="no" ?>
<WndPos name="Login" l="703" r="1264" t="323" b="909" />
<WndPos name="Main" l="703" r="768" t="323" b="609" />
<LayerManager />
<ViewLayers name="Roof" roof="1">
<Layer level="1" visible="1" />
</ViewLayers>
<DirProfiles>
<ProfileInfo ProfileName="Control1" DatabasePath="D:\Database\Control1" />
<ProfileInfo ProfileName="Control2" DatabasePath="D:\Database\Control2" />
<ProfileInfo ProfileName="Control3" DatabasePath="D:\Database\Control3" />
<ProfileInfo ProfileName="Control4" DatabasePath="D:\Database\Control4" />
<ProfileInfo ProfileName="Control5" DatabasePath="D:\Database\Control5" />
</DirProfiles>
<DirHistory>
<ProfileInfo Use="Database" Path="D:\Database\Control" />
</DirHistory>
This result xml fragment I have to write to the file which should be fragmented xml file (without root element).
I tried to do the following:
doc.Save();
But it saves with root element and application can't work with this xml.

Sum same named xml nodes

I have edited this little MSDN example https://support.microsoft.com/en-us/kb/311530
And I have the following 2 XML's
Book1.xml
<?xml version="1.0"?>
<catalog>
<book1 id="1" />
<bookSum number="1" />
</catalog>
Book2.xml
<?xml version="1.0"?>
<catalog>
<book2 id="2" />
<bookSum number="1" specialAttribute="123" />
</catalog>
C# Code
XmlReader xmlreader1 = XmlReader.Create(#"C:\Book1.xml");
XmlReader xmlreader2 = XmlReader.Create(#"C:\book2.xml");
DataSet ds = new DataSet();
ds.ReadXml(xmlreader1);
DataSet ds2 = new DataSet();
ds2.ReadXml(xmlreader2);
ds.Merge(ds2);
ds.WriteXml(#"C:\Merge.xml");
Console.WriteLine("Completed merging XML documents");
Merge.xml (Book1.xml + Book2.xml)
<?xml version="1.0" standalone="yes"?>
<catalog>
<book1 id="1" />
<bookSum number="1" />
<bookSum number="1" specialAttribute="x" />
<book2 id="2" />
</catalog>
And the question is
how to join
<bookSum number="1" />
<bookSum number="1" specialAttribute="123" />
into one line ?
<bookSum number="2" specialAttribute="123" />
I did it this way and is working:
var doc = XDocument.Load(#"C:\Book1.xml");
doc.Root.Add(XDocument.Load(#"C:\Book2.xml").Root.Elements()); // merged
var sum = doc.Descendants("bookSum").Attributes("number").Sum(t => int.Parse(t.Value));
var xElement = new XElement("bookSum", new XAttribute("number", sum));
foreach(var attrib in doc.Descendants("bookSum").Attributes())
{
if (xElement.Attribute(attrib.Name) == null)
xElement.Add(attrib);
}
doc.Descendants("bookSum").ToList().ForEach(t => t.ReplaceWith(xElement));
doc.Root.Descendants("bookSum").First().Remove();
Console.WriteLine(doc);

C#/XML Populate TreeView with XML file

im trying to populate a treeview from a xml file.
Image of the output: http://i.stack.imgur.com/3HSCu.png
So as you can see the parents are loaded well, but the childs (the elements) not. All the child nodes are loaded in all parent nodes. But the xml is not like that.
This is the XML code:
<?xml version="1.0" encoding="utf-8" ?>
<toolbox>
<parent id="p1" caption="All Elements" class="parent">
<element id="1" name="Button" />
<element id="2" name="Label" />
<element id="3" name="Inputfield" />
<element id="4" name="Textarea" />
<element id="5" name="Image" />
<element id="6" name="Background" />
<element id="7" name="TreeView" />
</parent>
<parent id="p2" caption="Some Elements 1" class="parent">
<element id="1" name="Button" />
<element id="2" name="Label" />
<element id="3" name="Inputfield" />
</parent>
<parent id="p3" caption="Some Elements 2" class="parent">
<element id="4" name="Textarea" />
<element id="5" name="Image" />
<element id="6" name="Background" />
<element id="7" name="TreeView" />
</parent>
</toolbox>
This is the C# code:
public void loadElements(string XML_Elements, TreeView Elements_Tree){
XmlDocument XMLDocument = new XmlDocument();
XMLDocument.Load(XML_Elements);
Elements_Tree.Nodes.Clear();
Elements_Tree.BeginUpdate();
XmlNodeList XMLParent = XMLDocument.SelectNodes("toolbox/parent");
foreach(XmlNode xmlparent in XMLParent){
//add parents
string Parent_Caption = xmlparent.Attributes["caption"].Value;
TreeNode parents = Elements_Tree.Nodes.Add(Parent_Caption);
//add childs
XmlNodeList XMLChilds = XMLDocument.SelectNodes("toolbox/parent/element");
foreach (XmlNode xmlchild in XMLChilds)
{
string Child_Name = xmlchild.Attributes["name"].Value;
parents.Nodes.Add(Child_Name);
}
}
}
You have to search for elements only within current parent element. Try that:
XmlNodeList XMLChilds = XMLDocument.SelectNodes("toolbox/parent[#caption='" + Parent_Caption + "']/element");
Or maybe even better:
XmlNodeList XMLChilds = xmlparent.SelectNodes("element");
XMLDocument.SelectNodes("toolbox/parent/element") selects all nodes that match in the document. You need to get the children of the current XmlNode, not start at the XMLDocument.

How can I filter xml sections and save it as a file

I am a beginner in using LINQ. I have an xml data with the format below
<Root>
<Global>
</Global>
<local>
<element name="A">
<subelement name="A">
<element name="A1">
<subelement name="A1">
<Property>
</Property>
</subelement>
</element>
<element name="B">
<Property>
</Property>
</element>
</subelement>
<subelement name="B">
<element name="A">
<Property>
</Property>
</element>
<element name="B">
<Property>
</Property>
</element>
</subelement>
</element>
</local>
</Root>
I want to save each section of the Property element into it's own xml file as below while keeping the hierarchy structure intact
<Root>
<Global>
</Global>
<local>
<element name="A">
<subelement name="A">
<element name="A1">
<subelement name="A1">
<Property>
</Property>
</subelement>
</element>
</subelement>
</element>
</local>
</Root>
and
<Root>
<Global>
</Global>
<local>
<element name="A">
<subelement name="A">
<element name="B">
<Property>
</Property>
</element>
</subelement>
</element>
</local>
</Root>
and so on for all the Property elements. Each element can have a child subelement and each subelement can have element child
Can you provide a solution on how to save each section of Property element as a new xml file with the current hierarchy structure intact. I have tried using the Ancestor() method of the XElement class
XDocument xml = XDocument.Load(filename);
XDocument convertedQuery = new XDocument(
new XElement(xml.Root.Name, from x in xml.Descendants("local")
select x.Ancestors())
);
but it is returning other Property elements as well, as below
<Root>
<Global></Global>
<local>
<element name="A">
<subelement name="A">
<element name="A1">
<subelement name="A1">
<Property></Property>
</subelement>
</element>
<element name="B">
<Property></Property>
</element>
</subelement>
<subelement name="B">
<element name="A">
<Property></Property>
</element>
<element name="B">
<Property></Property>
</element>
</subelement>
</element>
</local>
Any help would be much appreciated. Thanks
Here is some C# sample that should do what you want or at least give you an idea on how to approach that. The sample for testing simply writes each created XDocument to Console.Out but of course you could change that to save to a file on disk:
static void Main(string[] args)
{
XDocument doc = XDocument.Load(#"..\..\XMLFile1.xml");
foreach (XElement prop in doc.Descendants("Property"))
{
XDocument result = new XDocument(
new XElement(doc.Root.Name, doc.Root.Attributes(),
doc.Root.Elements("Global"),
CopySubtree(prop.Ancestors("local").First(), prop)));
result.Save(Console.Out);
Console.WriteLine();
}
}
static XElement CopySubtree(XElement ancestor, XElement descendant)
{
if (ancestor == descendant)
{
return descendant;
}
else
{
return
new XElement(
ancestor.Name,
ancestor.Attributes(),
CopySubtree(
ancestor
.Elements()
.First(e => e.DescendantsAndSelf().Any(d => d == descendant)),
descendant));
}
}
[edit]
For the new requirement to copy not only the Property ancestors but also its siblings you could adapt above method as follows:
static XElement CopySubtree(XElement ancestor, XElement descendant)
{
if (ancestor == descendant.Parent)
{
return ancestor;
}
else
{
return
new XElement(
ancestor.Name,
ancestor.Attributes(),
CopySubtree(
ancestor
.Elements()
.First(e => e.DescendantsAndSelf().Any(d => d == descendant)),
descendant));
}
}

C# XML De serialization and arrays

There is next xml file:
<element Name="root">
<SubFields>
<element Name="subroot">
<SubFields>
<element1 Name="element1" customatt1 = "12313" customatt2 = "asdfasfadsfasd">
<subelement Name="subelement" />
</element1>
<element1 Name="element11" customatt1 = "12313" customatt2 = "asdfasfadsfasd">
<subelement Name="subelement" />
</element1>
<element1 Name="element111" customatt1 = "12313" customatt2 = "asdfasfadsfasd">
<subelement Name="subelement" />
</element1>
<element2 Name="element2" path = "asdfdsf" widget="asdasdasd">
<subelement Name="subelement" />
</element2>
<element2 Name="element22" path = "asdfdsf" widget="asdasdasd">
<subelement Name="subelement" />
</element2>
<element2 Name="element222" path = "asdfdsf" widget="asdasdasd">
<subelement Name="subelement" />
</element2>
</SubFields>
</element>
</SubFields>
</element>
I mapped the array of elements as [XmlArray("SubFields")] where SubFields is root of arrays and Question:
How to map differences types of elements in object ?
And I can have a lot of subroot -s elements.
I used xsd.exe to do it.
Use the XMLSerializer class. Near the bottom theres a section about using Property attributes to map the object to the xml elements

Categories

Resources