问题
I am looking to see if there is a simple way to deserialize an XML file filled with elements back to a class of properties, specifically on the elements attribute 'name' as the property to attach to. For example, I have an XML file format given as:
<?xml version="1.0" encoding="utf-8"?>
<settings>
<setting name="number_val_one">1</setting>
<setting name="string_val_one">test</setting>
<setting name="number_val_two">42</setting>
<setting name="string_val_two">hello world</setting>
</settings>
I am wondering if there is a simple way to deserialize this back to a class that is similar to this format:
public class SomeObject
{
[XmlElement("number_value_one")]
public Int32 NumberValueOne { get; set; }
[XmlElement("number_value_two")]
public Int32 NumberValueTwo { get; set; }
[XmlElement("string_value_one")]
public String StringValueOne { get; set; }
[XmlElement("string_value_two")]
public String StringValueTwo { get; set; }
}
I understand the format is no the best for serialization and such but I cannot change how the file is formatted for this project. At the moment I am reading each element by hand for its value which is a lot of code and fairly messy. To serialize it back to xml I am using reflection to get around the need to write each element by hand. But I am wondering if there is a simple way to handle this format.
Not all elements are string / int though, some are custom types to be parsed after being read etc.
回答1:
For one you can use xslt to transform you input string to data recognizable by XmlSerializer
.
var transform = new XslCompiledTransform();
transform.Load(XmlReader.Create(new StringReader(transformText)));
var memoryStream = new MemoryStream();
transform.Transform(new XPathDocument(new StringReader(text)),null,memoryStream);
memoryStream.Seek(0, SeekOrigin.Begin);
var deserializer = new XmlSerializer(typeof(SomeObject)).Deserialize(memoryStream);
where
var transformText = @"
<xsl:stylesheet version=""1.0"" xmlns:xsl=""http://www.w3.org/1999/XSL/Transform"">
<xsl:output method=""xml"" encoding=""utf-8"" indent=""no""/>
<xsl:template match=""/"">
<SomeObject>
<xsl:for-each select=""settings/setting"">
<xsl:element name=""{@name}"">
<xsl:value-of select="".""/>
</xsl:element>
</xsl:for-each>
</SomeObject>
</xsl:template>
</xsl:stylesheet>";
and
var text = @"
<settings>
<setting name=""number_val_one"">1</setting>
<setting name=""string_val_one"">test</setting>
<setting name=""number_val_two"">42</setting>
<setting name=""string_val_two"">hello world</setting>
</settings>";
note that setting
name
attribute value must mach with XmlElementAttribute
applied to property.
If you don't understand xslt just search for it there is a lot of examples and references out there.
来源:https://stackoverflow.com/questions/14093422/deserialize-elements-to-properties-based-on-attribute