I am deserializing an Xml file into a .NET class, modifying properties, then serializing back into the same file. This is the .NET model (vb.net)
<XmlRoot("StationSetpoints")>
Public Class XmlStationSetpoints
<XmlElement("Setpoint")>
Public Property Setpoints As List(Of XmlStationSetpointsSetpoint)
End Class
<Serializable>
Public Class XmlStationSetpointsSetpoint
<XmlElement("Point")>
Public Property Points As List(Of XmlStationSetpointsSetpointPoint)
' etc...
End Class
Deserialization and serialization (c#)
var settings = New XmlStationSetpoints();
var serializer = New XmlSerializer(XmlStationSetpoints);
// deserialize
using StreamReader sr = new StreamReader(path)
settings = (XmlStationSetpoints)serializer.Deserialize(sr);
// serialize
using StreamWriter sw = new StreamWriter(path, false)
serializer.Serialize(sw, settings);
The original Xml file, including my local schema file which resides next to the Xml file xsi:schemaLocation="http://www.w3schools.com StationSetpoints.xsd"
(line 5)
<?xml version="1.0" encoding="utf-8"?>
<StationSetpoints
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xsi:schemaLocation="http://www.w3schools.com StationSetpoints.xsd">
<Setpoint PartNumber="108022">
<Point InstrumentName="PD Stage" Value="10"/>
</Setpoint>
<Setpoint PartNumber="107983">
<Point Order="2" InstrumentName="PD Stage" Value="7.5"/>
</Setpoint>
</StationSetpoints>
When the file is serialized, that schema path is not included
<?xml version="1.0" encoding="utf-8"?>
<StationSetpoints
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Setpoint PartNumber="108022">
<Point Order="0" InstrumentName="PD Stage" Value="10"></Point>
</Setpoint>
<Setpoint PartNumber="107983">
<Point Order="2" InstrumentName="PD Stage" Value="7.5"></Point>
</Setpoint>
</StationSetpoints>
How can I preserve that schema path in the .NET class, so that the serialized file includes it?
CodePudding user response:
You can deserialize and re-serialize the xsi:schemaLocation
attribute by adding an explicit property for that purpose, as shown in this answer by dtb to XmlSerialization and xsi:SchemaLocation (xsd.exe), suitably translated to VB.NET:
Public Partial Class XmlStationSetpoints
<XmlAttribute("schemaLocation", Namespace:="http://www.w3.org/2001/XMLSchema-instance")>
Public Property xsiSchemaLocation As String = "http://www.w3schools.com StationSetpoints.xsd"
End Class
Demo fiddle #1 here.
If you would like to hardcode the value of xsi:schemaLocation
and have it appear unconditionally when serializing, you may do so with an explicitly implemented property like so:
Public Partial Class XmlStationSetpoints
<XmlAttribute("schemaLocation", Namespace:="http://www.w3.org/2001/XMLSchema-instance")>
Public Property xsiSchemaLocation() As String
Get
Return "http://www.w3schools.com StationSetpoints.xsd"
End Get
Set
' Do nothing, it's hardcoded. A setter is required because XmlSerializer will only serialize properties with public getters and setters.
End Set
End Property
End Class
Demo fiddle #2 here.
And if you would like to hardcode the value of xsi:schemaLocation
but control whether or not it appears (because e.g. it should only appear when XmlStationSetpoints
is the root element of the XML file) you may do so with an xsiSchemaLocationSpecified
property like so:
Public Partial Class XmlStationSetpoints
<XmlAttribute("schemaLocation", Namespace:="http://www.w3.org/2001/XMLSchema-instance")>
Public Property xsiSchemaLocation() As String
Get
Return "http://www.w3schools.com StationSetpoints.xsd"
End Get
Set
' Do nothing, it's hardcoded. A setter is required because XmlSerializer will only serialize properties with public getters and setters.
End Set
End Property
<XmlIgnore>
Public Property xsiSchemaLocationSpecified() As Boolean
End Class
The property will capture whether the xsi:schemaLocation
property was encountered during deserialization, and will control whether the property is emitted during serialization.
Demo fiddle #3 here.