1 /**
2  * Copyright: Copyright (c) 2010-2011 Jacob Carlborg.
3  * Authors: Jacob Carlborg
4  * Version: Initial created: Jun 26, 2010
5  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0)
6  */
7 module mambo.xml.XmlDocument;
8 
9 import tango.text.xml.DocPrinter;
10 import tango.text.xml.Document;
11 import tango.io.Stdout;
12 
13 import mambo.core._;
14 
15 /**
16  * Evaluates to $(D_PARAM T) if $(D_PARAM T) is a character type. Otherwise this
17  * template will not compile.
18  */
19 template Char (T)
20 {
21 	static if (is(T == char) || is(T == wchar) || is(T == dchar))
22 		alias T Char;
23 
24 	else
25 		static assert(false, `The given type "` ~ T.stringof ~ `" is not a vaild character type, valid types are "char", "wchar" and "dchar".`);
26 }
27 
28 /// This class represents an exception thrown by XmlDocument.
29 class XMLException : Exception
30 {
31 	this (string message, string file = null, size_t line = 0)
32 	{
33 		super(message, file, line);
34 	}
35 }
36 
37 /**
38  * This class represents an XML DOM document. It provides a common interface to the XML
39  * document implementations available in Phobos and Tango.
40  */
41 final class XmlDocument (T = char)
42 {
43 	/// The type of the document implementation.
44 	alias Document!(T) Doc;
45 
46 	/// The type of the node implementation.
47 	alias Doc.Node Node;
48 
49 	/// The type of the query node implementation.
50 	//alias XmlPath!(T).NodeSet QueryNode;
51 
52 	///
53 	alias const(T)[] tstring;
54 
55 	/// The type of the visitor type implementation.
56 	alias Doc.Visitor VisitorType;
57 
58 	/// Set this to true if there should be strict errro checking.
59 	bool strictErrorChecking;
60 
61 	/// The number of spaces used for indentation used when printing the document.
62 	uint indentation = 4;
63 
64 	private Doc doc;
65 	private DocPrinter!(T) printer;
66 
67 	/**
68 	 * Creates a new instance of this class
69 	 *
70 	 * Examples:
71 	 * ---
72 	 * auto doc = new XmlDocument!();
73 	 * ---
74 	 *
75 	 * Params:
76 	 *     strictErrorChecking = true if strict errro checking should be enabled
77 	 */
78 	this (bool strictErrorChecking = true)
79 	{
80 		doc = new Doc;
81 		this.strictErrorChecking = strictErrorChecking;
82 	}
83 
84 	/**
85 	 * Attaches a header to the document.
86 	 *
87 	 * Examples:
88 	 * ---
89 	 * auto doc = new XmlDocument!();
90 	 * doc.header("UTF-8");
91 	 * // <?xml version="1.0" encoding="UTF-8"?>
92 	 * ---
93 	 *
94 	 * Params:
95 	 *     encoding = the encoding that should be put in the header
96 	 *
97 	 * Returns: the receiver
98 	 */
99 	XmlDocument header (tstring encoding = null)
100 	{
101 		doc.header(encoding);
102 
103 		return this;
104 	}
105 
106 	/// Rests the reciver. Allows to parse new content.
107 	XmlDocument reset ()
108 	{
109 		doc.reset;
110 
111 		return this;
112 	}
113 
114 	/// Return the root document node, from which all other nodes are descended.
115 	Node tree ()
116 	{
117 		return doc.tree;
118 	}
119 
120 	/**
121 	 * Parses the given string of XML.
122 	 *
123 	 * Params:
124 	 *     xml = the XML to parse
125 	 */
126 	void parse (tstring xml)
127 	{
128 		doc.parse(xml);
129 	}
130 
131 	/// Return an xpath handle to query this document. This starts at the document root.
132 	auto query ()
133 	{
134 		return doc.tree.query;
135 		//return QueryProxy(doc.tree.query);
136 	}
137 
138 	/// Pretty prints the document.
139 	override string toString ()
140 	{
141 		if (!printer)
142 			printer = new DocPrinter!(T);
143 
144 		printer.indent = indentation;
145 		auto str = printer.print(doc);
146 
147 		return str.assumeUnique;
148 	}
149 
150 	/**
151 	 * Attaches a new node to the docuement.
152 	 *
153 	 * Params:
154 	 *     name = the name of the node
155 	 *     value = the vale of the node
156 	 *
157 	 * Returns: returns the newly created node
158 	 */
159 	Node createNode (tstring name, tstring value = null)
160 	{
161 		return tree.element(null, name, value).detach;
162 	}
163 }