簡體   English   中英

如何使用XmlSerializer屬性解析此XML?

[英]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屬性或需要盡可能少的樣板代碼的任何其他方式。

我編寫了foobar元素名稱,但我需要解析的XML結構基於完全相同的約定。

我當然可以在這些類中手動實現IXmlSerializable ,或者只使用FooBar類並使用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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM