![](/img/trans.png)
[英]How can I parse a deserialized property (during deserialization) using XmlSerializer?
[英]How can I parse this XML with XmlSerializer attributes?
我們需要使用“Web服務”來傳達極其丑陋的XML。 它不是由我們開發的,並且沒有機會使其開發人員理解正確的XML。
僅供參考,這個Web服務也接受HTTP GET URL參數(而不是請求體)中的相同類型的XML - 開發它的人不明白為什么這是一個不好的做法。
那么,映射XML的最快方法是什么,例如:
<foo id="document">
<foo id="customer">
<bar name="firstname" value="Joe"/>
<bar name="lastname" value="Smith"/>
<foo id="address">
<bar name="city" value="New York"/>
<bar name="country" value="USA"/>
</foo>
</foo>
<bar name="somemoredata1" value="123"/>
<bar name="somemoredata2" value="abc"/>
</foo>
進入這樣的類:
public class Document
{
public Customer Customer { get; set; }
public int SomeMoreData1 { get; set; }
public string SomeMoreData2 { get; set; }
}
public class Customer
{
public Address Address { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
public class Address
{
public string City { get; set; }
public string Country { get; set; }
}
使用例如。 XML Serializer屬性或需要盡可能少的樣板代碼的任何其他方式。
我編寫了foo
和bar
元素名稱,但我需要解析的XML結構基於完全相同的約定。
我當然可以在這些類中手動實現IXmlSerializable
,或者只使用Foo
和Bar
類並使用XmlSerializer
,但這些選項都不是一個好的解決方案。
提前感謝您的回答!
我自己沒有使用過xml序列化程序或反序列化程序,但我確實使用LINQ將我的XML文檔解析為對象。 如果您的課程相當簡單,您可以查看該路線。
您無法使用XML序列化程序屬性執行此操作:無法使其從指定的屬性中獲取字段名稱。 您將不得不手動反序列化(可能生成樣板)或預處理XML - 沿着以下行的簡單XSLT將起到作用:
<xsl:template match="foo">
<xsl:element name="{@id}">
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
<xsl:template match="bar">
<xsl:element name="{@name}">
<xsl:value-of select="@value"/>
</xsl:element>
</xsl:template>
更新:用於反向轉換:
<xsl:template match="*[count(child::text())=1]">
<bar value="{text()}" name="{local-name()}"/>
</xsl:template>
<xsl:template match="*">
<foo id="{local-name()}">
<xsl:apply-templates/>
</foo>
</xsl:template>
既然你在評論中說你為了簡單而為了XmlSerializer而苦苦掙扎,而不是因為這種方法是由其他問題強制執行的,這里有一個不同的方法。 由於在文檔中似乎元素的名稱無關緊要,我在解析中忽略它,盡管也可以測試它。 使用更令人愉快的XML格式,這將是解析將關鍵的主要內容(通常使用元素名稱上的switch
):
private static Document ParseDocument(XmlReader xr)
{
Document doc = new Document();
while(xr.Read())
if(xr.NodeType == XmlNodeType.Element)
if(xr.GetAttribute("id") == "customer")
doc.Customer = ParseCustomer(xr.ReadSubtree());
else
switch(xr.GetAttribute("name"))
{
case "somemoredata1":
doc.SomeMoreData1 = int.Parse(xr.GetAttribute("value"));
break;
case "somemoredata2":
doc.SomeMoreData2 = xr.GetAttribute("value");
break;
}
//Put some validation of doc here if necessary.
return doc;
}
private static Customer ParseCustomer(XmlReader xr)
{
Customer cu = new Customer();
while(xr.Read())
if(xr.NodeType == XmlNodeType.Element)
if(xr.GetAttribute("id") == "address")
cu.Address = ParseAddress(xr.ReadSubtree());
else
switch(xr.GetAttribute("name"))
{
case "firstname":
cu.FirstName = xr.GetAttribute("value");
break;
case "lastname":
cu.LastName = xr.GetAttribute("value");
break;
}
//validate here if necessary.
return cu;
}
private static Address ParseAddress(XmlReader xr)
{
Address add = new Address();
while(xr.Read())
if(xr.NodeType == XmlNodeType.Element)
switch(xr.GetAttribute("name"))
{
case "city":
add.City = xr.GetAttribute("value");
break;
case "country":
add.Country = xr.GetAttribute("value");
break;
}
return add;
}
它並不完全漂亮(它不是非常漂亮,有很好的XML可以解決,但它往往不會那么糟糕),但它可以工作,並且使用子樹可以很好用一些復雜的結構,同一類型可以出現在文檔內的不同位置。 可以使用構造函數替換從外部設置值的靜態方法,這些構造函數采用XmlReader
,允許確保類不變量,和/或使對象不可變。
這種方法進入了自己在要deserialise作為大型系列相同種類的物品(或大型系列短短類型)的大文件的情況下,因為可以yield
,因為它們可以創造出來,這可以對第一次響應的延遲產生很大影響。
您可以嘗試“XML Schema Definition-Tool”( http://msdn.microsoft.com/de-de/library/x6c1kb0s%28v=vs.80%29.aspx )
再見! 斯特凡
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.