2012-04-04 18 views
1

本当に嫌なことは、Xmlファイルから各要素や属性の値をキャストすることです。キャストなしでXmlから値を保存して取得する方法は?

私は何百ものモジュールで、オブジェクトをXmlFileに変換する方法を指定するメソッドを作成しています。信じて、これは非常に疲れている。だから私は代替案を考えている。

私はXSDについて調査していましたが、これが私の救済になるかどうかはわかりません。私はXMLにLinqを使用して値を保存して取得しています。つまり、オブジェクトは次のように構成されています。

- 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の値を設定しますAttribute、および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); 

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

へ:

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

はGetEnumerable()メソッドを使用します新しいintのリストを設定してください:

この新しいXMLになり
var list2 = new int[] { 1, 3, 4, 5, 6, 7, 8, 9, 0 }; 
root.SetEnumerable("path/list", list2, a => new XElement("value", a)); 

:私たちはXDocumentの周りに強く種類のクラスラッパーを作成するためにLinq To Xsdを使用

<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構造を表現するクラスを作成してデシリアライズすることはできます。例えば

:私は頻繁に部分的にこの正確な理由のために、私はデフォルトを持っていないので、XML構造を検証するためにXSDを使用

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

私の最初はしかしXmlSerializationでしたが、私のデザインで私は多くのlimitarionsを見つけました'm最後の解決策として検討するつもりです。このファイルをデータベースとして使用しています。つまり、追加、更新、削除を意味します。 –

0

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


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

次に、あなたがこれを使用しますコンストラクタやプライベートフィールドを持っている場合、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), 
      } 

EDIT:「

をコメントに対応するための情報を追加あなたは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ファイルの作成方法を教えてください。 –

+0

Visual Studioを使用している場合は、IDEから直接XMLからXSDを作成できます。 XSDの基本的なフレームワークが完成すれば、あなたのニーズに合ったテーラーにすることができます。私は自分の答えを編集して、この情報のいくつかを含めて、あなたを始められるようにします。 – psubsee2003

0

<?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> 

その後、同じ名前のクラスにアクセスすることができます:

あなたはちょうどあなたがcsprojファイルにLinqToXsdをハッキングしたら(スキーマファイル(XSD)を書いて、あなたのプロジェクトに含める

私は...(私は多くのインターフェイスを使用して、ほとんど私のクラスは、デフォルトコンストラクタを持っていないので、それができるでしょう)任意の方法
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.

関連する問題