要擴大西蒙的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
}
對於標準的Xml串行器來說,輸入過於具體,無法做到這一點。我認爲你可以在標準的標準反序列化之前運行XSL轉換,但是它可能更容易編寫自定義c#...你也可以看看IXmlSerializable接口 –
@SimonMourier我會一直建議DTO模型(模型在域模型和序列化表單之間,與序列化層相匹配)在'IXmlSerializable'之前 - 該API是* horrendous *以便正確。我確實喜歡這裏的XSLT。 –
作爲一個便箋:誰想出了該XML佈局......不知道如何XML; p –