mirror of
https://github.com/claunia/plist-cil.git
synced 2025-12-16 19:14:26 +00:00
Implement XmlPropertyListParser
This commit is contained in:
@@ -1,3 +1,10 @@
|
||||
2015-02-19 Natalia Portillo <claunia@claunia.com>
|
||||
|
||||
* plist-cil.csproj:
|
||||
* PropertyListParser.cs:
|
||||
* XmlPropertyListParser.cs:
|
||||
Implement XmlPropertyListParser
|
||||
|
||||
2015-02-19 Natalia Portillo <claunia@claunia.com>
|
||||
|
||||
* UID.cs:
|
||||
|
||||
@@ -145,8 +145,7 @@ namespace Claunia.PropertyList
|
||||
case TYPE_BINARY:
|
||||
return BinaryPropertyListParser.Parse(f);
|
||||
case TYPE_XML:
|
||||
// TODO: Implement XMLPropertyListParser
|
||||
//return XMLPropertyListParser.parse(f);
|
||||
return XmlPropertyListParser.Parse(f);
|
||||
case TYPE_ASCII:
|
||||
return ASCIIPropertyListParser.Parse(f);
|
||||
default:
|
||||
@@ -164,8 +163,7 @@ namespace Claunia.PropertyList
|
||||
case TYPE_BINARY:
|
||||
return BinaryPropertyListParser.Parse(bytes);
|
||||
case TYPE_XML:
|
||||
// TODO: Implement XMLPropertyListParser
|
||||
//return XMLPropertyListParser.parse(bytes);
|
||||
return XmlPropertyListParser.Parse(bytes);
|
||||
case TYPE_ASCII:
|
||||
return ASCIIPropertyListParser.Parse(bytes);
|
||||
default:
|
||||
|
||||
201
plist-cil/XmlPropertyListParser.cs
Normal file
201
plist-cil/XmlPropertyListParser.cs
Normal file
@@ -0,0 +1,201 @@
|
||||
// plist-cil - An open source library to parse and generate property lists for .NET
|
||||
// Copyright (C) 2015 Natalia Portillo
|
||||
//
|
||||
// This code is based on:
|
||||
// plist - An open source library to parse and generate property lists
|
||||
// Copyright (C) 2014 Daniel Dreibrodt
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
using System;
|
||||
using System.Xml;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace Claunia.PropertyList
|
||||
{
|
||||
/// <summary>
|
||||
/// Parses XML property lists.
|
||||
/// </summary>
|
||||
/// @author Daniel Dreibrodt
|
||||
public static class XmlPropertyListParser
|
||||
{
|
||||
/// <summary>
|
||||
/// Parses a XML property list file.
|
||||
/// </summary>
|
||||
/// <param name="f">The XML property list file.</param>
|
||||
/// <returns>The root object of the property list. This is usually a NSDictionary but can also be a NSArray.</returns>
|
||||
public static NSObject Parse(FileInfo f) {
|
||||
XmlDocument doc = new XmlDocument();
|
||||
doc.Load(f.OpenRead());
|
||||
|
||||
return ParseDocument(doc);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parses a XML property list from a byte array.
|
||||
/// </summary>
|
||||
/// <param name="bytes">The byte array containing the property list's data.</param>
|
||||
/// <returns>The root object of the property list. This is usually a NSDictionary but can also be a NSArray.</returns>
|
||||
public static NSObject Parse(byte[] bytes) {
|
||||
MemoryStream bis = new MemoryStream(bytes);
|
||||
return Parse(bis);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parses a XML property list from an input stream.
|
||||
/// </summary>
|
||||
/// <param name="str">The input stream pointing to the property list's data.</param>
|
||||
/// <returns>The root object of the property list. This is usually a NSDictionary but can also be a NSArray.</returns>
|
||||
public static NSObject Parse(Stream str) {
|
||||
XmlDocument doc = new XmlDocument();
|
||||
doc.Load(str);
|
||||
|
||||
return ParseDocument(doc);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parses the XML document by generating the appropriate NSObjects for each XML node.
|
||||
/// </summary>
|
||||
/// <returns>The root NSObject of the property list contained in the XML document.</returns>
|
||||
/// <param name="doc">The XML document.</param>
|
||||
private static NSObject ParseDocument(XmlDocument doc) {
|
||||
XmlDocumentType docType = doc.DocumentType;
|
||||
if (docType == null) {
|
||||
if (!doc.DocumentElement.Name.Equals("plist")) {
|
||||
throw new XmlException("The given XML document is not a property list.");
|
||||
}
|
||||
} else if (!docType.Name.Equals("plist")) {
|
||||
throw new XmlException("The given XML document is not a property list.");
|
||||
}
|
||||
|
||||
XmlNode rootNode;
|
||||
|
||||
if (doc.DocumentElement.Name.Equals("plist")) {
|
||||
//Root element wrapped in plist tag
|
||||
List<XmlNode> rootNodes = FilterElementNodes(doc.DocumentElement.ChildNodes);
|
||||
if (rootNodes.Count == 0) {
|
||||
throw new PropertyListFormatException("The given XML property list has no root element!");
|
||||
} else if (rootNodes.Count == 1) {
|
||||
rootNode = rootNodes[0];
|
||||
} else {
|
||||
throw new PropertyListFormatException("The given XML property list has more than one root element!");
|
||||
}
|
||||
} else {
|
||||
//Root NSObject not wrapped in plist-tag
|
||||
rootNode = doc.DocumentElement;
|
||||
}
|
||||
|
||||
return ParseObject(rootNode);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parses a node in the XML structure and returns the corresponding NSObject
|
||||
/// </summary>
|
||||
/// <returns>The corresponding NSObject.</returns>
|
||||
/// <param name="n">The XML node.</param>
|
||||
private static NSObject ParseObject(XmlNode n) {
|
||||
if (n.Name.Equals("dict")) {
|
||||
NSDictionary dict = new NSDictionary();
|
||||
List<XmlNode> children = FilterElementNodes(n.ChildNodes);
|
||||
for (int i = 0; i < children.Count; i += 2) {
|
||||
XmlNode key = children[i];
|
||||
XmlNode val = children[i + 1];
|
||||
|
||||
string keyString = GetNodeTextContents(key);
|
||||
|
||||
dict.Add(keyString, ParseObject(val));
|
||||
}
|
||||
return dict;
|
||||
} else if (n.Name.Equals("array")) {
|
||||
List<XmlNode> children = FilterElementNodes(n.ChildNodes);
|
||||
NSArray array = new NSArray(children.Count);
|
||||
for (int i = 0; i < children.Count; i++) {
|
||||
array.SetValue(i, ParseObject(children[i]));
|
||||
}
|
||||
return array;
|
||||
} else if (n.Name.Equals("true")) {
|
||||
return new NSNumber(true);
|
||||
} else if (n.Name.Equals("false")) {
|
||||
return new NSNumber(false);
|
||||
} else if (n.Name.Equals("integer")) {
|
||||
return new NSNumber(GetNodeTextContents(n));
|
||||
} else if (n.Name.Equals("real")) {
|
||||
return new NSNumber(GetNodeTextContents(n));
|
||||
} else if (n.Name.Equals("string")) {
|
||||
return new NSString(GetNodeTextContents(n));
|
||||
} else if (n.Name.Equals("data")) {
|
||||
return new NSData(GetNodeTextContents(n));
|
||||
} else if (n.Name.Equals("date")) {
|
||||
return new NSDate(GetNodeTextContents(n));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns all element nodes that are contained in a list of nodes.
|
||||
/// </summary>
|
||||
/// <returns>The sublist containing only nodes representing actual elements.</returns>
|
||||
/// <param name="list">The list of nodes to search.</param>
|
||||
private static List<XmlNode> FilterElementNodes(XmlNodeList list) {
|
||||
List<XmlNode> result = new List<XmlNode>();
|
||||
foreach (XmlNode child in result) {
|
||||
if (child.NodeType == XmlNodeType.Element) {
|
||||
result.Add(child);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a node's text content.
|
||||
/// This method will return the text value represented by the node's direct children.
|
||||
/// If the given node is a TEXT or CDATA node, then its value is returned.
|
||||
/// </summary>
|
||||
/// <returns>The node's text content.</returns>
|
||||
/// <param name="n">The node.</param>
|
||||
private static string GetNodeTextContents(XmlNode n) {
|
||||
if (n.NodeType == XmlNodeType.Text || n.NodeType == XmlNodeType.CDATA) {
|
||||
string content = n.Value; //This concatenates any adjacent text/cdata/entity nodes
|
||||
if (content == null)
|
||||
return "";
|
||||
else
|
||||
return content;
|
||||
} else {
|
||||
if (n.HasChildNodes) {
|
||||
XmlNodeList children = n.ChildNodes;
|
||||
|
||||
foreach (XmlNode child in children) {
|
||||
//Skip any non-text nodes, like comments or entities
|
||||
if (child.NodeType == XmlNodeType.Text || child.NodeType == XmlNodeType.CDATA) {
|
||||
string content = child.Value; //This concatenates any adjacent text/cdata/entity nodes
|
||||
if (content == null)
|
||||
return "";
|
||||
else
|
||||
return content;
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
} }
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Numerics" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
@@ -47,6 +48,7 @@
|
||||
<Compile Include="ASCIIPropertyListParser.cs" />
|
||||
<Compile Include="BinaryPropertyListParser.cs" />
|
||||
<Compile Include="BinaryPropertyListWriter.cs" />
|
||||
<Compile Include="XmlPropertyListParser.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
<ProjectExtensions>
|
||||
|
||||
Reference in New Issue
Block a user