Reputation: 119
I have an xml file
<?xml version="1.0" encoding="utf-8"?>
<ArrayOfLocations xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Location xsi:type="JointLocation">
<Name>Example Location</Name>
<Index>0</Index>
<ZClearance>0</ZClearance>
<Joint1>100</Joint1>
<Joint2>200</Joint2>
<Joint3>200</Joint3>
<Joint4>200</Joint4>
<Joint5>200</Joint5>
<joint6>0</joint6>
<Joint6>0</Joint6>
</Location>
</ArrayOfLocations>
I load this file into a data set, and then into a DataGridView. From that DataGridView I can add new Location elements, or edit existing Location elements and save. When I save, I am doing this
string path = filePathBox.Text;
DataSet ds = (DataSet)dataGridView1.DataSource;
ds.WriteXml(filePathBox.Text);
After saving, the XML file then looks like
<?xml version="1.0" standalone="yes"?>
<ArrayOfLocations>
<Location>
<Name>Example Location</Name>
<Index>0</Index>
<ZClearance>0</ZClearance>
<Joint1>100</Joint1>
<Joint2>200</Joint2>
<Joint3>200</Joint3>
<Joint4>200</Joint4>
<Joint5>200</Joint5>
<joint6>0</joint6>
<Joint6>0</Joint6>
</Location>
</ArrayOfLocations>
As you can see the xsi and namespace have been removed. I would like to preserve these attributes.
So far I have tried adding as an additional parameter to WriteXML():
ds.WriteXML(filepath, XmlWriteMode.WriteSchema)
However, this creates a big mess and still does not maintain the initial format that I want to preserve. Any tips?
Upvotes: 0
Views: 184
Reputation: 856
A simple example shows us that ReadXML
/WriteXML
will lose the schema info you're interested in
using (FileStream fs = new FileStream("D:\\Workspace\\FormTest\\input.xml", FileMode.Open))
{
DataSet ds = new DataSet();
ds.ReadXml(fs);
ds.WriteXml(Console.Out);
}
Gives us
<ArrayOfLocations>
<Location>
<Name>Example Location</Name>
<Index>0</Index>
<ZClearance>0</ZClearance>
<Joint1>100</Joint1>
<Joint2>200</Joint2>
<Joint3>200</Joint3>
<Joint4>200</Joint4>
<Joint5>200</Joint5>
<joint6>0</joint6>
<Joint6>0</Joint6>
</Location>
</ArrayOfLocations>
The best way I found to recover this schema information is to Deserialize
the data. It's not pretty but it worked for me:
XmlSerializer s = new XmlSerializer(typeof(ArrayOfLocations));
ArrayOfLocations fix = new ArrayOfLocations();
using (FileStream fs = new FileStream("D:\\Workspace\\FormTest\\input.xml", FileMode.Open))
{
DataSet ds = new DataSet();
ds.ReadXml(fs);
string xml = ds.GetXml();
ArrayOfLocations input = (ArrayOfLocations)s.Deserialize(new StringReader(xml));
foreach(var location in input)
{
fix.Add(new JointLocation()
{
Name = location.Name,
...
Joint6 = location.Joint6
});
}
}
XmlTextWriter xtw = new XmlTextWriter(Console.Out);
xtw.Formatting = Formatting.Indented;
s.Serialize(xtw, fix);
And of course you'll need to create the classes that model your schema in order to deserialize:
public class Location
{
public string Name { get; set; }
...
public byte Joint6 { get; set; }
}
public class JointLocation : Location { }
[XmlInclude(typeof(JointLocation))]
[XmlRoot("ArrayOfLocations")]
public class ArrayOfLocations : List<Location> { }
Note the following gotchas
JoinLocation
class, specify that type under XmlInclude
, and manually fix your object all in order to comply with the schema that you want to output to.XmlTextWritter
to respect indentationThis all should give you the desired output:
<?xml version="1.0" encoding="Codepage - 437"?>
<ArrayOfLocations xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Location xsi:type="JointLocation">
<Name>Example Location</Name>
<Index>0</Index>
<ZClearance>0</ZClearance>
<Joint1>100</Joint1>
<Joint2>200</Joint2>
<Joint3>200</Joint3>
<Joint4>200</Joint4>
<Joint5>200</Joint5>
<Joint6>0</Joint6>
</Location>
</ArrayOfLocations>
Upvotes: 0