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>
|
2015-02-19 Natalia Portillo <claunia@claunia.com>
|
||||||
|
|
||||||
* UID.cs:
|
* UID.cs:
|
||||||
|
|||||||
@@ -145,8 +145,7 @@ namespace Claunia.PropertyList
|
|||||||
case TYPE_BINARY:
|
case TYPE_BINARY:
|
||||||
return BinaryPropertyListParser.Parse(f);
|
return BinaryPropertyListParser.Parse(f);
|
||||||
case TYPE_XML:
|
case TYPE_XML:
|
||||||
// TODO: Implement XMLPropertyListParser
|
return XmlPropertyListParser.Parse(f);
|
||||||
//return XMLPropertyListParser.parse(f);
|
|
||||||
case TYPE_ASCII:
|
case TYPE_ASCII:
|
||||||
return ASCIIPropertyListParser.Parse(f);
|
return ASCIIPropertyListParser.Parse(f);
|
||||||
default:
|
default:
|
||||||
@@ -164,8 +163,7 @@ namespace Claunia.PropertyList
|
|||||||
case TYPE_BINARY:
|
case TYPE_BINARY:
|
||||||
return BinaryPropertyListParser.Parse(bytes);
|
return BinaryPropertyListParser.Parse(bytes);
|
||||||
case TYPE_XML:
|
case TYPE_XML:
|
||||||
// TODO: Implement XMLPropertyListParser
|
return XmlPropertyListParser.Parse(bytes);
|
||||||
//return XMLPropertyListParser.parse(bytes);
|
|
||||||
case TYPE_ASCII:
|
case TYPE_ASCII:
|
||||||
return ASCIIPropertyListParser.Parse(bytes);
|
return ASCIIPropertyListParser.Parse(bytes);
|
||||||
default:
|
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>
|
<ItemGroup>
|
||||||
<Reference Include="System" />
|
<Reference Include="System" />
|
||||||
<Reference Include="System.Numerics" />
|
<Reference Include="System.Numerics" />
|
||||||
|
<Reference Include="System.Xml" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
@@ -47,6 +48,7 @@
|
|||||||
<Compile Include="ASCIIPropertyListParser.cs" />
|
<Compile Include="ASCIIPropertyListParser.cs" />
|
||||||
<Compile Include="BinaryPropertyListParser.cs" />
|
<Compile Include="BinaryPropertyListParser.cs" />
|
||||||
<Compile Include="BinaryPropertyListWriter.cs" />
|
<Compile Include="BinaryPropertyListWriter.cs" />
|
||||||
|
<Compile Include="XmlPropertyListParser.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||||
<ProjectExtensions>
|
<ProjectExtensions>
|
||||||
|
|||||||
Reference in New Issue
Block a user