如何通过使用唯一标识符作为属性的重复标签名称来反序列化XML?

时间:2018-07-13 18:10:53

标签: c# xmlserializer

我正在尝试反序列化此xml,其中所有节点都具有相同的名称,并且具有唯一的标识符作为属性。

<configuration>
    <setting name="host">
        <value>127.0.0.1</value>
    </setting>
    <setting name="port">
        <value>80</value>
    </setting>
</configuration>

我想要达到的结果是:

public class Configuration
{
    string host { get; set; }
    int port { get; set; }
}

我阅读了前面的问题,但我仍然为它们具有相同的标签名称而感到困惑。

谢谢!

3 个答案:

答案 0 :(得分:2)

您可以称这为“老派”,但它可以工作。

  1. 复制XML(或片段等)并利用Visual Studio(2015年(?),向上-拍摄于2017年)功能“将XML / JSON作为类粘贴”

    Visual Studio 2017

    这对有效的有效XML 很有帮助-尤其是用于装饰生成的类的“ proper”属性。此外,它只是一个类,因此您可以根据需要自定义它(同时保留属性)。

    对于更复杂的XML(例如名称空间/前缀),您将非常感激。如果您没有此工具,则可以使用XSD.exe(甚至更古老的学校)-对XML文档执行相同的操作。

  2. 上述步骤中自动生成的类:

      

    ...因为标签名称相同而感到困惑...

    不要。 XML元素可以重复-经常重复(例如,每个网站都有sitemap.xml)。生成的类将帮助您精通它。这是一个标准的集合/数组/列表。

    [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
    [System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = false)]
    public partial class configuration
    {
    
        private configurationSetting[] settingField;
    
        /// <remarks/>
        [System.Xml.Serialization.XmlElementAttribute("setting")]
        public configurationSetting[] setting
        {
            get
            {
                return this.settingField;
            }
            set
            {
                this.settingField = value;
            }
        }
    }
    
    [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
    public partial class configurationSetting
    {
    
        private string valueField;
    
        private string nameField;
    
        /// <remarks/>
        public string value
        {
            get
            {
                return this.valueField;
            }
            set
            {
                this.valueField = value;
            }
        }
    
        /// <remarks/>
        [System.Xml.Serialization.XmlAttributeAttribute()]
        public string name
        {
            get
            {
                return this.nameField;
            }
            set
            {
                this.nameField = value;
            }
        }
    }
    

鉴于以上所述,您可以执行以下操作:

string rawXml = "<configuration><setting name=\"host\"><value>127.0.0.1</value></setting><setting name=\"port\"><value>80</value></setting></configuration>";

var ser = new XmlSerializer(typeof(configuration));
configuration config;
using (TextReader rdr = new StringReader(rawXml))
{
    config = (configuration)ser.Deserialize(rdr);
}


foreach (configurationSetting setting in config.setting)
{
    Console.WriteLine($"{setting.name} = {setting.value}");
}

输出:

host = 127.0.0.1
port = 80

Hth ..

答案 1 :(得分:1)

将xml加载为文档

XmlDocument doc = new XmlDocument();
doc.LoadXml(your_xml_data);

然后遍历子节点

Configuration configuration = new Configuration();
XmlNode root = doc.FirstChild;

//fill the configuration from the child nodes.
if (root.HasChildNodes)
{
 if(root.ChildNodes[0].Name == "host")
 {
    configuration.host = root.ChildNodes[0].InnerText;
 }
 if(root.ChildNodes[1].Name == "port")
 {   
    configuration.port = root.ChildNodes[1].InnerText;
 }
}

答案 2 :(得分:1)

尝试一下:

        XmlDocument doc = new XmlDocument();
        doc.LoadXml("yourxmlhere");

        Configuration configuration = new Configuration();
        XmlNode root = doc.FirstChild;
        if (root.HasChildNodes)
        {
            foreach (XmlNode item in root.ChildNodes)
            {
                configuration = SetValueByPropertyName(configuration, item.Attributes["name"].Value, item.FirstChild.InnerText);
            }
        }

设置值的辅助方法:

public static TInput SetValueByPropertyName<TInput>(TInput obj, string name, string value)
        {
            PropertyInfo prop = obj.GetType().GetProperty(name);
            if (null != prop && prop.CanWrite)
            {
                if (prop.PropertyType != typeof(String))
                {
                    prop.SetValue(obj, Convert.ChangeType(value, prop.PropertyType), null);
                }
                else
                {
                    prop.SetValue(obj, value, null);
                }
            }
            return obj;
        }