2012-04-04 20 views
1

我真正討厭的東西是從Xml文件中轉換每個元素或屬性值。如何保存並從Xml中獲取值而不需要轉換?

這個組件,我在數百個模塊中創建了一個方法,它指定了如何將對象轉換爲XmlFile。相信,這很累。所以我在想另一種方法。

我正在調查XSD,我不確定這是否會成爲我的救贖。我使用Linq to Xml來保存並獲取值。我的意思是,我的物體是這樣組成的:

- Foo1 : Foo 
    - Range1 : Range 
     - X : int 
     - Y : int 
- ... 

正如你所看到的,它們有許多節點。有沒有另外一種方法來做到這一點?我的意思是,強烈的類型。

回答

1

您可以嘗試以下的XElement擴展方法:http://searisen.com/xmllib/extensions.wiki

這裏是它的權力的一個例子,因爲這個XML從另一篇文章:

<?xml version="1.0" encoding="utf-8"?> 
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"> 
    <PatchCreation 
    Id="224C316C-5894-4771-BABF-21A3AC1F75FF" 
    CleanWorkingFolder="yes" 
    OutputPath="patch.pcp" 
    WholeFilesOnly="yes"> 
    <PatchInformation 
     Description="Update Patch" 
     Comments="Update Patch" 
     ShortNames="no" 
     Languages="1033" 
     Compressed="yes" 
     Manufacturer="me"/> 

    <PatchMetadata 
     AllowRemoval="yes" 
     Description="Update Patch" 
     ManufacturerName="me" 
     TargetProductName="Update" 
     MoreInfoURL="http://andrewherrick.com/" 
     Classification="Update" 
     DisplayName="Update Patch"/> 

    <Family DiskId="5000" 
     MediaSrcProp="Sample" 
     Name="Update" 
     SequenceStart="5000"> 
     <UpgradeImage SourceFile="c:\new.msi" Id="PatchUpgrade"> 
     <TargetImage SourceFile="c:\old.msi" Order="2" Id="PatchUpgrade" IgnoreMissingFiles="no" /> 
     </UpgradeImage> 
    </Family> 

    <PatchSequence PatchFamily="SamplePatchFamily" 
     Sequence="1.0.0.0" 
     Supersede="yes" /> 
    </PatchCreation> 
</Wix> 

這臺UpgradeImage標籤的的SourceFile的價值UpgradeImage及其SourceFile中的屬性和TargetImage標記。

XElement wix = XElement.Load(xmlFile1.FullName); 
wix.Set("PatchCreation/Family/UpgradeImage/SourceFile", "upgrade path", true) 
    .Set("TargetImage/SourceFile", "target path", true); 

你也可以用同樣的方式獲得它們的值(沒有強制轉換)。

string upgradeSource = wix.Get("PatchCreation/Family/UpgradeImage/SourceFile", string.Empty); 
string targetSource = wix.Get("PatchCreation/Family/UpgradeImage/TargetImage/SourceFile", string.Empty); 

或者,這可以寫成:

XElement upgradeImage = wix.GetElement("PatchCreation/Family/UpgradeImage"); 
string upgradeSource = upgradeImage.Get("SourceFile", string.Empty); 
string targetSource = upgradeImage.Get("TargetImage/SourceFile", string.Empty); 

爲了得到一個整數列表:

<root> 
<path> 
    <list> 
    <value>1</value> 
    <value>12</value> 
    <value>13</value> 
    <value>14</value> 
    <value>15</value> 
    </list> 
    </path> 
</root> 

使用GetEnumerable()方法:

List<int> list = root 
    .GetEnumerable("path/list/value", xvalue => xvalue.Get(null, int.MinValue)); 
    .ToList(); 

要設置一個新的int列表:

var list2 = new int[] { 1, 3, 4, 5, 6, 7, 8, 9, 0 }; 
root.SetEnumerable("path/list", list2, a => new XElement("value", a)); 

導致這種新的XML:

<root> 
    <path> 
    <list> 
     <value>1</value> 
     <value>3</value> 
     <value>4</value> 
     <value>5</value> 
     <value>6</value> 
     <value>7</value> 
     <value>8</value> 
     <value>9</value> 
     <value>0</value> 
    </list> 
    </path> 
</root> 
0

最好的辦法是使用XmlSerialization。所以序列化到XML然後反序列化爲對象,那麼你不必使用轉換。

有時XML是通過序列化以外的其他方式創建的。但是,您仍然可以創建表示您的XML結構和反序列化的類。

例如:

Public Class Foo 
{ 
    public Range Range {get; set;} 
} 


public class Range 
{ 
    public int X {get; set;} 
    public int Y {get; set;} 
} 

然後你使用這樣的:

XmlSerializer ser = new XmlSerializer(typeof(Foo)); 
+0

我的第一個雖然是XmlSerialization,但在我的設計,我發現有很多limitarions(這將是因爲我用了很多接口,幾乎我的課沒有默認構造函數)..無論如何,我「M去考慮它作爲最後的解決方案:)我使用這個文件作爲數據庫,我的意思是,增加,更新,刪除.. – 2012-04-04 16:20:44

0

我經常使用的XSD驗證XML結構,部分爲這個確切的原因,因爲我沒有默認建設者和/或私人領域,XMLSerialization往往不是一個選項。

如果XML驗證沒有錯誤,然後我繼續使用Linq2Xml和使用各種Parse(String s)方法在我的課需要的類型得到的數據,但我還沒有找到一個乾淨的解決方案卻會做到這一點,沒有任何形式的轉換。

驗證步驟避免了由於數據類型不正確而導致的異常。

var query = from tst in xml.Elements("test") 
      select new 
      { 
       int1 = Int32.Parse(tst.Element("int1").Value), 
       double1 = Double.Parse(tst.Element("double1").Value), 
       double2 = Double.Parse(tst.Element("double2").Value), 
      } 

編輯:添加信息,以迴應評論」

您可以從Visual Studio GUI直接創建XSD並且有做到這一點其他的工具,但我通常使用Visual Studio從XML菜單在編輯器中,打開XML,然後選擇「創建模式」(路徑顯示在快照)。

XML to XSD in Visual Studio IDE

生成的XSD是非常基本的,它試圖通過並「猜測」每個節點的適當數據類型,並且不包含任何其他限制,但它將框架放在一起爲您提供了體面的工作。

完成之後,您可以進入並調整數據類型以更好地滿足您的需求(如果需要),並且您可以將自己的限制添加到數據中(例如要求xs:int值的範圍爲0和50或xs:string值的長度小於10個字符 - 有幾十個其他可能性,但是這應該給你這個想法)。

我其實剛剛玩過XSD語言,而且越做越容易。 W3Schools網站是無價的。

+0

你能告訴我如何創建你的XSD文件? – 2012-04-04 17:39:04

+0

如果您使用Visual Studio,則可以直接在IDE中使用XML創建XSD。一旦你擁有了XSD的基本框架,你就可以進入並滿足你的需求。我將編輯我的答案,以包含一些此信息以幫助您入門。 – psubsee2003 2012-04-04 17:53:38

0

我們使用Linq To Xsd強烈創建XDocument周圍種類包裝。

你只寫一個模式文件(XSD),幷包括在您的項目(一旦你砍死LinqToXsd到的csproj文件:

<?xml version="1.0" encoding="UTF-8"?> 
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> 
    <xs:element name="Foo1"> 
     <xs:complexType> 
      <xs:sequence> 
       <xs:element name="Range1"> 
        <xs:complexType> 
         <xs:sequence> 
          <xs:element name="X" type="xs:int"/> 
          <xs:element name="Y" type="xs:int"/> 
         </xs:sequence> 
        </xs:complexType> 
       </xs:element> 
      </xs:sequence> 
     </xs:complexType> 
    </xs:element> 
</xs:schema> 

然後你就可以訪問同名的類:

Foo1 foo = new Foo1() 
{ 
    Range1 = new Foo1.Range1() 
    { 
     X = 7, 
     Y = 10, 
    } 
}; 

foo.Save(foo.xml); 

var input = Foo1.Load(input.xml); 

Console.WriteLine(input.Range1.X.ToString()); 

J.