XML 从属性到属性的反序列化
XML Deserialization from attributes to properties
如何像这样反序列化 xml:
<query>
<parameters>
<param name="lastUpdate">2012-05-25</param>
<param name="code">11222122</param>
<param name="type">idnLookup</param>
</parameters>
<response>
<category name="person" version="1">
<field name="surname">Soap</field>
<field name="name1">Joe</field>
<field name="date_of_birth">1973-05-09</field>
</category>
<category name="contact" version="1">
<row>
<field name="phone">0118063433</field>
<field name="type">home</field>
<field name="date">2003-01-01</field>
</row>
<row>
<field name="phone">0124666566</field>
<field name="type">home</field>
<field name="date">2008-03-11</field>
</row>
</category>
</response>
</query>
变成这样的 class 结构:
public class Query{
public string lastUpdate {get;set;}
public string code {get;set;}
public string type {get;set;}
public Response response {get;set;}
}
class Response{
public Person person {get;set;}
public Contact[] contacts {get;set;}
}
class Person {
public string surname {get;set;}
public string name1 {get;set;}
public string date_of_birth {get;set;}
}
class Contact {
public string phone {get;set;}
public string type {get;set;}
public string date {get;set;}
}
使用标准的 .net xml 序列化程序。还是我需要自己动手?
要扩展 Simon 的 xslt 想法,请考虑以下 xslt:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/query/parameters">
<xsl:apply-templates select="*"/>
<!-- removes a level from the hierarchy by applying directly -->
</xsl:template>
<xsl:template match="*[@name]">
<xsl:element name="{@name}">
<xsl:apply-templates select="@*[name()!='name'] | * | text()"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
此处的关键匹配项是 *[@name]
,它采用以下任何形式:
<foo name="abc" ...>...</foo>
并将其重写为:
<abc ...>...</abc>
这会将您的 xml 转换为:
<query>
<lastUpdate>2012-05-25</lastUpdate>
<code>11222122</code>
<type>idnLookup</type>
<response>
<person version="1">
<surname>Soap</surname>
<name1>Joe</name1>
<date_of_birth>1973-05-09</date_of_birth>
</person>
<contact version="1">
<row>
<phone>0118063433</phone>
<type>home</type>
<date>2003-01-01</date>
</row>
<row>
<phone>0124666566</phone>
<type>home</type>
<date>2008-03-11</date>
</row>
</contact>
</response>
</query>
可以通过非常小的调整将其映射到您的模型作为属性:
[XmlRoot("query")] // <==== add this
public class Query {...}
[XmlArray("contact"), XmlArrayItem("row")] // <=== add this
public Contact[] contacts { get; set; }
可以使用哪个,例如:
static void Main()
{
XslCompiledTransform xslt = new XslCompiledTransform();
xslt.Load("my.xslt");
var sw = new StringWriter();
xslt.Transform("my.xml", null, sw);
var transformedXml = sw.ToString();
Console.WriteLine(transformedXml);
Query query;
using (var reader = XmlReader.Create(new StringReader(transformedXml)))
{
query = (Query)new XmlSerializer(typeof(Query)).Deserialize(reader);
}
// query is now fully populated
}
试试这个
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using System.IO;
namespace ConsoleApplication32
{
class Program
{
const string FILENAME = @"c:\temp\Test.xml";
static void Main(string[] args)
{
XmlSerializer xs = new XmlSerializer(typeof(Query));
XmlTextReader reader = new XmlTextReader(FILENAME);
Query query = (Query)xs.Deserialize(reader);
query.Response.GetContacts();
}
}
[XmlRoot("query")]
public class Query
{
[XmlElement("parameters")]
public Parameters Parameters {get;set;}
[XmlElement("response")]
public Response Response {get;set;}
}
[XmlRoot("parameters")]
public class Parameters{
private string lastUpdate {get;set;}
private string code {get;set;}
private string type {get;set;}
[XmlElement("param")]
public List<Param> m_params {get; set;}
}
[XmlRoot("param")]
public class Param
{
[XmlAttribute("name")]
public string name {get; set;}
}
[XmlRoot("response")]
public class Response
{
private Person person {get;set;}
private List<Contact> contacts = new List<Contact>();
[XmlElement("category")]
public List<Category> categories {get;set;}
public void GetContacts()
{
foreach (Category category in categories)
{
string catName = category.name;
switch (catName)
{
case "person" :
person = new Person();
foreach (Field field in category.fields)
{
switch (field.name)
{
case "surname" :
person.surname = field.value;
break;
case "name1":
person.name1 = field.value;
break;
case "date_of_birth":
person.date_of_birth = field.value;
break;
default :
break;
}
}
break;
case "contact" :
foreach (Row row in category.row)
{
Contact newContact = new Contact();
contacts.Add(newContact);
foreach (Field field in row.fields)
{
switch (field.name)
{
case "phone":
newContact.phone = field.value;
break;
case "type":
newContact.type = field.value;
break;
case "date":
newContact.date = field.value;
break;
default:
break;
}
}
}
break;
}
}
}
}
[XmlRoot("category")]
public class Category
{
[XmlAttribute("name")]
public string name {get; set;}
[XmlAttribute("version")]
public string version { get; set; }
[XmlElement("field")]
public List<Field> fields {get; set;}
[XmlElement("row")]
public List<Row> row {get;set;}
}
[XmlRoot("row")]
public class Row
{
[XmlElement("field")]
public List<Field> fields {get; set;}
}
[XmlRoot("field")]
public class Field
{
[XmlAttribute("name")]
public string name { get; set; }
[XmlText]
public string value { get; set; }
}
class Person {
public string surname {get;set;}
public string name1 {get;set;}
public string date_of_birth {get;set;}
}
class Contact {
public string phone {get;set;}
public string type {get;set;}
public string date {get;set;}
}
}
如何像这样反序列化 xml:
<query>
<parameters>
<param name="lastUpdate">2012-05-25</param>
<param name="code">11222122</param>
<param name="type">idnLookup</param>
</parameters>
<response>
<category name="person" version="1">
<field name="surname">Soap</field>
<field name="name1">Joe</field>
<field name="date_of_birth">1973-05-09</field>
</category>
<category name="contact" version="1">
<row>
<field name="phone">0118063433</field>
<field name="type">home</field>
<field name="date">2003-01-01</field>
</row>
<row>
<field name="phone">0124666566</field>
<field name="type">home</field>
<field name="date">2008-03-11</field>
</row>
</category>
</response>
</query>
变成这样的 class 结构:
public class Query{
public string lastUpdate {get;set;}
public string code {get;set;}
public string type {get;set;}
public Response response {get;set;}
}
class Response{
public Person person {get;set;}
public Contact[] contacts {get;set;}
}
class Person {
public string surname {get;set;}
public string name1 {get;set;}
public string date_of_birth {get;set;}
}
class Contact {
public string phone {get;set;}
public string type {get;set;}
public string date {get;set;}
}
使用标准的 .net xml 序列化程序。还是我需要自己动手?
要扩展 Simon 的 xslt 想法,请考虑以下 xslt:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/query/parameters">
<xsl:apply-templates select="*"/>
<!-- removes a level from the hierarchy by applying directly -->
</xsl:template>
<xsl:template match="*[@name]">
<xsl:element name="{@name}">
<xsl:apply-templates select="@*[name()!='name'] | * | text()"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
此处的关键匹配项是 *[@name]
,它采用以下任何形式:
<foo name="abc" ...>...</foo>
并将其重写为:
<abc ...>...</abc>
这会将您的 xml 转换为:
<query>
<lastUpdate>2012-05-25</lastUpdate>
<code>11222122</code>
<type>idnLookup</type>
<response>
<person version="1">
<surname>Soap</surname>
<name1>Joe</name1>
<date_of_birth>1973-05-09</date_of_birth>
</person>
<contact version="1">
<row>
<phone>0118063433</phone>
<type>home</type>
<date>2003-01-01</date>
</row>
<row>
<phone>0124666566</phone>
<type>home</type>
<date>2008-03-11</date>
</row>
</contact>
</response>
</query>
可以通过非常小的调整将其映射到您的模型作为属性:
[XmlRoot("query")] // <==== add this
public class Query {...}
[XmlArray("contact"), XmlArrayItem("row")] // <=== add this
public Contact[] contacts { get; set; }
可以使用哪个,例如:
static void Main()
{
XslCompiledTransform xslt = new XslCompiledTransform();
xslt.Load("my.xslt");
var sw = new StringWriter();
xslt.Transform("my.xml", null, sw);
var transformedXml = sw.ToString();
Console.WriteLine(transformedXml);
Query query;
using (var reader = XmlReader.Create(new StringReader(transformedXml)))
{
query = (Query)new XmlSerializer(typeof(Query)).Deserialize(reader);
}
// query is now fully populated
}
试试这个
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using System.IO;
namespace ConsoleApplication32
{
class Program
{
const string FILENAME = @"c:\temp\Test.xml";
static void Main(string[] args)
{
XmlSerializer xs = new XmlSerializer(typeof(Query));
XmlTextReader reader = new XmlTextReader(FILENAME);
Query query = (Query)xs.Deserialize(reader);
query.Response.GetContacts();
}
}
[XmlRoot("query")]
public class Query
{
[XmlElement("parameters")]
public Parameters Parameters {get;set;}
[XmlElement("response")]
public Response Response {get;set;}
}
[XmlRoot("parameters")]
public class Parameters{
private string lastUpdate {get;set;}
private string code {get;set;}
private string type {get;set;}
[XmlElement("param")]
public List<Param> m_params {get; set;}
}
[XmlRoot("param")]
public class Param
{
[XmlAttribute("name")]
public string name {get; set;}
}
[XmlRoot("response")]
public class Response
{
private Person person {get;set;}
private List<Contact> contacts = new List<Contact>();
[XmlElement("category")]
public List<Category> categories {get;set;}
public void GetContacts()
{
foreach (Category category in categories)
{
string catName = category.name;
switch (catName)
{
case "person" :
person = new Person();
foreach (Field field in category.fields)
{
switch (field.name)
{
case "surname" :
person.surname = field.value;
break;
case "name1":
person.name1 = field.value;
break;
case "date_of_birth":
person.date_of_birth = field.value;
break;
default :
break;
}
}
break;
case "contact" :
foreach (Row row in category.row)
{
Contact newContact = new Contact();
contacts.Add(newContact);
foreach (Field field in row.fields)
{
switch (field.name)
{
case "phone":
newContact.phone = field.value;
break;
case "type":
newContact.type = field.value;
break;
case "date":
newContact.date = field.value;
break;
default:
break;
}
}
}
break;
}
}
}
}
[XmlRoot("category")]
public class Category
{
[XmlAttribute("name")]
public string name {get; set;}
[XmlAttribute("version")]
public string version { get; set; }
[XmlElement("field")]
public List<Field> fields {get; set;}
[XmlElement("row")]
public List<Row> row {get;set;}
}
[XmlRoot("row")]
public class Row
{
[XmlElement("field")]
public List<Field> fields {get; set;}
}
[XmlRoot("field")]
public class Field
{
[XmlAttribute("name")]
public string name { get; set; }
[XmlText]
public string value { get; set; }
}
class Person {
public string surname {get;set;}
public string name1 {get;set;}
public string date_of_birth {get;set;}
}
class Contact {
public string phone {get;set;}
public string type {get;set;}
public string date {get;set;}
}
}