2011-11-15 69 views
3

我正在嘗試使用Windows窗體創建一個路點生成器,它允許用戶通過GUI創建路點數據& &將數據輸出到XML文件。我選擇利用內置的c#XML序列化功能,但無法以客戶端所需的方式格式化XML輸出。使用c#&windows窗體進行XML序列化

一個精簡的航點數據對象的版本看起來像下面這樣:

// Waypoint data class 
[XmlRoot("RootNode")] 
public class WaypointProjectData 
{ 
    [XmlElement("Map")]   // Also tried to use XmlElementAttribute, 
    [XmlAttribute("file")]   // XmlAttributeAttribute, and many variations 
            // of these qualifiers, with no success 
    public string  m_szMapImageFileName; 

    [XmlAttribute("width")] 
    public int   m_iWidth; 

    [XmlAttribute("height")] 
    public int   m_iHeight; 

    [XmlArray("Nodes")] 
    public ArrayList m_aoNodes; 

    WaypointProjectData() 
    { 
     m_szMapImageFileName = "map.png"; 
     m_aoNodes = new ArrayList(); 
    } 
} 

客戶要求XML輸出與以下佈局/格式符合:

<RootNode> 
    <Map file="map.png" width="100" height="100" /> 
    <OtherData var="variable" data="10" /> 
    <Nodes> 
    <Node x="10" y="30" /> 
    <Node x="30" y="20" /> // etc... 
    </Nodes> 
</RootNode> 

一些明確有關如何使用c#xml序列化來做到這一點的例子會很有幫助。謝謝!

+0

什麼部分不起作用? – BrokenGlass

+0

您可以使用XmlElement或XmlAttribute節點,但不能同時使用給定的屬性。也許爲每個XmlNode創建一個您需要的對象,映射到該元素的屬性,然後自己合併XML結果? –

+0

註釋掉[XmlElement(「Map」)]時,文件字符串,寬度和高度數據全部添加爲根節點的屬性。或者,當註釋掉[XmlAttribute(「file」)]時,文件字符串被放置在根節點之後的元素標記內,但寬度和高度仍然被放置爲根節點的屬性。 – GameDev

回答

0

一旦你離開了流行音樂系列化是一個龐大的PIA。 你需要一些東西來標記爲映射,也可能是OtherData,所以這意味着你需要一個對應於節點的類或結構。 例如WaypointProejctdata作爲類Map,它具有屬性filename,width和height。 我一般的經驗法則是,只要我必須開始搞弄我的對象來獲取xml,序列化得到裝箱,然後添加一個接口,它需要一個XmlReader或Writer並實現它。 Tryng讓序列化做你想做的事情通常是更多的代碼,並且比這樣做更難理解。

1

當我不得不以這種特定的Xml格式序列化某些東西時,我從一個模式開始(必要時推斷,如果知道,手工製作)。然後我使用VS xsd工具創建序列化類(是的,我知道xsd可以用於推理架構部分—我只是從來沒有爲此目的而打擾它)。

所以,如果你有這樣一個從你的例子創建的XSD文件(注意,我指定的數據類型儘可能—這有助於使用適當類型的屬性的XSD工具):

<?xml version="1.0" encoding="UTF-8"?> 
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified"> 
    <xs:element name="RootNode"> 
     <xs:complexType> 
      <xs:sequence> 
       <xs:element name="Map"> 
        <xs:complexType> 
         <xs:attribute name="file" type="xs:string"/> 
         <xs:attribute name="width" type="xs:decimal"/> 
         <xs:attribute name="height" type="xs:decimal"/> 
        </xs:complexType> 
       </xs:element> 
       <xs:element name="OtherData"> 
        <xs:complexType> 
         <xs:attribute name="var" type="xs:string"/> 
         <xs:attribute name="data" type="xs:decimal"/> 
        </xs:complexType> 
       </xs:element> 
       <xs:element name="Nodes" minOccurs="0"> 
        <xs:complexType> 
         <xs:sequence> 
          <xs:element name="Node" maxOccurs="unbounded"> 
           <xs:complexType> 
            <xs:attribute name="x" type="xs:decimal"/> 
            <xs:attribute name="y" type="xs:decimal"/> 
           </xs:complexType> 
          </xs:element> 
         </xs:sequence> 
        </xs:complexType> 
       </xs:element> 
      </xs:sequence> 
     </xs:complexType> 
    </xs:element> 
</xs:schema> 

如果命名此Root.xsd,那麼你可以去到VS命令行,並運行

XSD Root.xsd/C /n:myProject.Xml

這將創建一個類文件(名爲根.cs,因爲這是處理Root時的默認值。 xsd),其中包含的對象可以輕鬆插入.Net以序列化和反序列化XML。請注意,我指定了類將具有的名稱空間(「/n:myProject.Xml」)。我更喜歡控制這個名字空間,但其餘的默認通常很好。此外,該工具會創建部分類,因此如果您需要自定義屬性訪問器,則可以將它們添加到單獨的文件中,如果需要再次運行該工具,則該文件不會得到creamed。

另一個提示,我在我的項目中創建了一個名爲「< xsd name > xsd Command Line.txt」的文本文件。這樣我只需將它粘貼到VS命令行中,不必記住我使用的所有其他東西。

+0

我很欣賞它做出這種迴應所付出的努力,但它確實不能回答我的問題。從航點生成器輸出的文件必須遵循特定的佈局,以便與客戶端軟件兼容。上面的例子不僅與這種格式相差甚遠,它還缺少我所要求的:用於創建輸出的c#實現的一個示例。謝謝你的迴應。 – GameDev

+0

將該模式複製到xsd中並運行VS xsd工具,您就可以準確找到要查找的內容:即用於創建輸出的c#實現示例。我認爲這很清楚。我沒有包含實際的自動生成的代碼,因爲我想你會想自己調整它以實現你真正想要的結果。畢竟,沒有人真的需要一個名爲「OtherData」的節點,其屬性爲「var」和「data」... –

+0

哦,哎呀。我誤解了你的帖子意思是說我有一個(模式)格式的生成器輸出,然後通過另一個(部分)程序將該文件轉換爲所需的格式,這看起來像是一種迂迴的方式來達到最終結果。感謝您的澄清。 我會圍繞VS xsd/schema工具捅一捅,看看我能想出什麼。 – GameDev