Deserialize elements to properties based on attribute

大兔子大兔子 提交于 2019-12-21 20:28:09

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!