2012-02-08 8 views
2

iOSアプリをWP7に変換しています。私がしたいのは、自分のWP7アプリでiOSアプリケーション用に作成したplistファイルを変更せずに使用することです。私はここからhttp://codetitans.codeplex.com/のライブラリを使ってみましたが、私は1つのレベルを解析することしかできませんでした。私のplistは複数のレベルを持っています。WPOSのiOS .plistファイルを解析する

<?xml version="1.0" encoding="UTF-8"?> 
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> 
<plist version="1.0"> 
    <dict> 
    <key>section0</key> 
    <dict> 
     <key>key0</key> 
     <dict> 
      <key>name</key> 
      <string>Title</string> 
      <key>type</key> 
      <string>text</string> 
      <key>filter</key> 
      <false/> 
     </dict> 
     <key>key1</key> 
     <dict> 
      <key>name</key> 
      <string>Season</string> 
      <key>type</key> 
      <string>text</string>    
      <key>filter</key> 
      <false/>   
     </dict> 
    </dict> 
    </dict> 
+0

セクションまたはネストされた名前/値のペアのみが必要ですか? –

答えて

4

パート1:それを解析しながら、WPは現在、とてもダイナミックなタイプのために非常に良いサポートを持っていないあなたは

を求めここで私が解析しようとしているplistファイルの例です。困難ではないでしょう、消費すると醜いでしょう。

このクラスは、XMLにLINQを使用し、PLISTを解析します:

public class PropertyListParser 
{ 
    public IDictionary<String, Object> Parse(string plistXml) 
    { 
     return Parse(XDocument.Parse(plistXml)); 
    } 

    public IDictionary<String, Object> Parse(XDocument document) 
    { 
     return ParseDictionary(document.Root.Elements("plist") 
      .Elements("dict") 
      .First()); 
    } 

    private IDictionary<String, Object> ParseDictionary(XElement dictElement) 
    { 
     return dictElement 
      .Elements("key") 
      .ToDictionary(
       el => el.Value, 
       el => ParseValue(el.ElementsAfterSelf("*").FirstOrDefault()) 
      ); 
    } 

    private object ParseValue(XElement element) 
    { 
     if (element == null) 
     { 
      return null; 
     } 

     string valueType = element.Name.LocalName; 

     switch (valueType) 
     { 
      case "string": 
       return element.Value; 
      case "dict": 
       return ParseDictionary(element); 
      case "true": 
       return true; 
      case "false": 
       return false; 
      default: 
       throw new NotSupportedException("Plist element not supported: " + valueType); 
     } 
    } 
} 

はここに(あなたの例に基づいて)それを使用する方法の例です:

var parsedPlist = new PlistParser().Parse(Plist); 

var section0 = (IDictionary<string, object>)parsedPlist["section0"]; 

var key0 = (IDictionary<string, object>)parsedPlist["key0"]; 

string type = (string)key0["type"]; 
bool filter = (bool)key0["filter"]; 

パート2:あなたは何おそらく必要です

実際にこの方法でそれを消費するコードを書くことはかなり醜いと言われています。あなたのスキーマに基づいて、私は次のことが実際にあなたのアプリケーションに必要なものだと言いたいと思います。

今、あなたは ConfigEntryLoaderを使用するとき、あなたは辞書の周りに渡すことを維持するために、あなたのコードがはるかに容易になりますConfigEntryオブジェクトのリストを取得
// I'm not sure what your domain object is, so please rename this 
public class ConfigEntry 
{ 
    public string Name { get; set; } 
    public string Type { get; set; } 
    public bool Filter { get; set; } 
} 

public class ConfigEntryLoader 
{ 
    private PropertyListParser plistParser; 

    public ConfigEntryLoader() 
    { 
     plistParser = new PropertyListParser(); 
    } 

    public ICollection<ConfigEntry> LoadEntriesFromPlist(string plistXml) 
    { 
     var parsedPlist = plistParser.Parse(plistXml); 

     var section0 = (IDictionary<string, object>)parsedPlist["section0"]; 

     return section0.Values 
      .Cast<IDictionary<string,object>>() 
      .Select(CreateEntry) 
      .ToList(); 
    } 

    private ConfigEntry CreateEntry(IDictionary<string, object> entryDict) 
    { 
     // Accessing missing keys in a dictionary throws an exception, 
     // so if they are optional you should check if they exist using ContainsKey 
     return new ConfigEntry 
     { 
      Name = (string)entryDict["name"], 
      Type = (string)entryDict["type"], 
      Filter = (bool)entryDict["filter"] 
     }; 
    } 
} 

ICollection<ConfigEntry> configEntries = new ConfigEntryLoader() 
    .LoadEntriesFromPlist(plistXml); 
1

実際には、CodeTitans Librariesはすべてのレベルを解析します。

[TestMethod] 
public void LoadMultilevelItems() 
{ 
    var input = @"<?xml version=""1.0"" encoding=""UTF-8""?> 
<!DOCTYPE plist PUBLIC ""-//Apple//DTD PLIST 1.0//EN"" ""http://www.apple.com/DTDs/PropertyList-1.0.dtd""> 
<plist version=""1.0""> 
    <dict> 
    <key>section0</key> 
    <dict> 
     <key>key0</key> 
     <dict> 
      <key>name</key> 
      <string>Title</string> 
      <key>type</key> 
      <string>text</string> 
      <key>filter</key> 
      <false/> 
     </dict> 
     <key>key1</key> 
     <dict> 
      <key>name</key> 
      <string>Season</string> 
      <key>type</key> 
      <string>text</string>    
      <key>filter</key> 
      <false/>   
     </dict> 
    </dict> 
    </dict> 
</plist>"; 

    var data = PropertyList.Read(input); 

    Assert.IsNotNull(data); 
    Assert.IsTrue(data.Contains("section0")); 

    var section0 = data["section0"]; 
    Assert.IsNotNull(section0); 
    Assert.IsTrue(section0.Contains("key0")); 

    var key0 = section0["key0"]; 
    Assert.IsNotNull(key0); 

    Assert.AreEqual("Title", key0["name"].StringValue); 
    Assert.AreEqual("text", key0["type"].StringValue); 
    Assert.IsFalse(key0["filter"].BooleanValue); 
    key0.Add("filter", true); 
} 

すべてのアイテムは、使用してアクセスすることができますデフォルト「辞書」または「配列」である:ここでは は、私はあなたが実際にネストされたアイテムにアクセスする方法を示しては、という、あなたのデータを今日追加ユニットテストです角かっこ。 値に達したときは、独自のコードで型キャストを避けるために、専用のプロパティ 'StringValue'または 'BooleanValue'を使用してください。

Type(アイテムのネイティブplistタイプを確認できるようにする)やArrayItemsやDictionaryItems(構造フォーマットが動的な場合はコンテンツを列挙できます)のようなサポートプロパティがあります。

関連する問題