1 /**
2  * Useful ae.utils.xml helpers
3  *
4  * License:
5  *   This Source Code Form is subject to the terms of
6  *   the Mozilla Public License, v. 2.0. If a copy of
7  *   the MPL was not distributed with this file, You
8  *   can obtain one at http://mozilla.org/MPL/2.0/.
9  *
10  * Authors:
11  *   Vladimir Panteleev <ae@cy.md>
12  */
13 
14 module ae.utils.xml.helpers;
15 
16 import std.algorithm.iteration;
17 import std.array;
18 
19 import ae.utils.xml.lite;
20 
21 /// Returns `true` if node `n` is a tag, and its tag name is `tag`.
22 bool isTag(XmlNode n, string tag, XmlNodeType type = XmlNodeType.Node)
23 {
24 	return n.type == type && n.tag ==  tag;
25 }
26 
27 /// Like `isTag`, but if `n` does not satisfy the criteria and it has one child node,
28 /// check it recursively instead. Returns the satisfying node or `null`.
29 XmlNode findOnlyChild(XmlNode n, string tag, XmlNodeType type = XmlNodeType.Node)
30 {
31 	return n.isTag(tag, type) ? n :
32 		n.children.length != 1 ? null :
33 		n.children[0].findOnlyChild(tag, type);
34 }
35 
36 /// ditto
37 XmlNode findOnlyChild(XmlNode n, XmlNodeType type)
38 {
39 	return n.type == type ? n :
40 		n.children.length != 1 ? null :
41 		n.children[0].findOnlyChild(type);
42 }
43 
44 /// Search recursively for all nodes which are tags and have the tag name `tag`.
45 XmlNode[] findNodes(XmlNode n, string tag)
46 {
47 	if (n.isTag(tag))
48 		return [n];
49 	return n.children.map!(n => findNodes(n, tag)).join;
50 }
51 
52 /// Create a new node with the given properties.
53 XmlNode newNode(XmlNodeType type, string tag, string[string] attributes = null, XmlNode[] children = null)
54 {
55 	auto node = new XmlNode(type, tag);
56 	node.attributes = attributes;
57 	node.children = children;
58 	return node;
59 }
60 
61 /// Create a tag new node with the given properties.
62 XmlNode newNode(string tag, string[string] attributes = null, XmlNode[] children = null)
63 {
64 	return newNode(XmlNodeType.Node, tag, attributes, children);
65 }
66 
67 /// Create a text node with the given contents.
68 XmlNode newTextNode(string text)
69 {
70 	return newNode(XmlNodeType.Text, text);
71 }