/// <summary> /// Default constructor. /// </summary> public PropertyList() { Root = new PropertyListDictionary(null); Version = new Version(1, 0); }
/// <summary> /// Reads the texts and interprets as PList definition. /// </summary> public static PropertyList Read(TextReader text) { try { XmlReaderSettings settings = new XmlReaderSettings(); #if NET_2_COMPATIBLE && !PocketPC && !WINDOWS_PHONE // obsolete, but will cause an exception at start-up if not set to false (crazy!) settings.ProhibitDtd = false; #endif #if !NET_2_COMPATIBLE settings.DtdProcessing = DtdProcessing.Ignore; #endif settings.IgnoreComments = true; settings.IgnoreProcessingInstructions = true; settings.IgnoreWhitespace = true; Version resultVersion = null; IPropertyListItem result = null; int intNumber; double doubleNumber; string key = null; Stack <IPropertyListItem> items = new Stack <IPropertyListItem>(); using (XmlReader reader = XmlReader.Create(text, settings)) { while (reader.Read()) { switch (reader.NodeType) { case XmlNodeType.Element: if (reader.Name == "plist") { if (resultVersion != null) { throw new FormatException("Secondary plist definition not expected"); } if (reader.MoveToAttribute("version")) { if (reader.ReadAttributeValue()) { resultVersion = new Version(reader.Value); } } break; } if (reader.Name == "key") { if (key != null) { throw new FormatException("Two keys in a row are not expected"); } if (reader.Read()) { key = reader.Value; } break; } if (reader.Name == "dict") { if (key == null) { if (result == null) { result = new PropertyListDictionary(null); if (!reader.IsEmptyElement) { items.Push(result); } break; } if (items.Peek().Type != PropertyListItemTypes.Array) { throw new FormatException("Found dictionary definition without key name"); } } // add new dictionary to the top collection: var newDictionary = items.Peek().AddNewDictionary(key); if (!reader.IsEmptyElement) { items.Push(newDictionary); } key = null; break; } if (reader.Name == "array") { if (key == null) { if (result == null) { result = new PropertyListArray(null); if (!reader.IsEmptyElement) { items.Push(result); } break; } if (items.Peek().Type != PropertyListItemTypes.Array) { throw new FormatException("Found array definition without key name"); } } // add new array to the top collection: var newArray = items.Peek().AddNewArray(key); if (!reader.IsEmptyElement) { items.Push(newArray); } key = null; break; } if (reader.Name == "string") { if (key == null && items.Peek().Type == PropertyListItemTypes.Dictionary) { throw new FormatException("Found string definition without key name"); } if (reader.Read()) { items.Peek().Add(key, reader.Value); } key = null; break; } if (reader.Name == "integer") { if (key == null && items.Peek().Type == PropertyListItemTypes.Dictionary) { throw new FormatException("Found integer definition without key name"); } if (reader.Read()) { if (NumericHelper.TryParseInt32(reader.Value, out intNumber)) { items.Peek().Add(key, intNumber); } else { throw new FormatException("Can not parse number: '" + reader.Value + "'"); } } key = null; break; } if (reader.Name == "real") { if (key == null && items.Peek().Type == PropertyListItemTypes.Dictionary) { throw new FormatException("Found real definition without key name"); } if (reader.Read()) { if (NumericHelper.TryParseDouble(reader.Value, NumberStyles.Float, out doubleNumber)) { items.Peek().Add(key, doubleNumber); } else { throw new FormatException("Can not parse number: '" + reader.Value + "'"); } } key = null; break; } if (reader.Name == "true") { if (key == null && items.Peek().Type == PropertyListItemTypes.Dictionary) { throw new FormatException("Found boolean definition without key name"); } items.Peek().Add(key, true); key = null; break; } if (reader.Name == "false") { if (key == null && items.Peek().Type == PropertyListItemTypes.Dictionary) { throw new FormatException("Found boolean definition without key name"); } items.Peek().Add(key, false); key = null; break; } if (reader.Name == "date") { if (key == null && items.Peek().Type == PropertyListItemTypes.Dictionary) { throw new FormatException("Found date definition without key name"); } if (reader.Read()) { items.Peek().Add(key, DateTime.Parse(reader.Value, CultureInfo.InvariantCulture)); } key = null; break; } if (reader.Name == "data") { if (key == null && items.Peek().Type == PropertyListItemTypes.Dictionary) { throw new FormatException("Found data definition without key name"); } if (reader.Read()) { items.Peek().Add(key, Convert.FromBase64String(reader.Value)); } key = null; break; } break; case XmlNodeType.EndElement: if (EndElement(items, reader.Name, "dict", PropertyListItemTypes.Dictionary)) { break; } if (EndElement(items, reader.Name, "array", PropertyListItemTypes.Array)) { break; } break; } } } if (items.Count > 0) { throw new FormatException("Not all items have been closed"); } return(new PropertyList(result, resultVersion)); } catch (Exception ex) { DebugLog.WriteCoreException(ex); throw; } }