The Birdfont Source Code


All Repositories / birdfont.git / blob – RSS feed

Xml.vala in libbirdxml

This file is a part of the Birdfont project.

Contributing

Send patches or pull requests to johan.mattsson.m@gmail.com.
Clone this repository: git clone https://github.com/johanmattssonm/birdfont.git

Revisions

View the latest version of libbirdxml/Xml.vala.
Give press event method a name
1 /* 2 Copyright (C) 2014 Johan Mattsson 3 4 This library is free software; you can redistribute it and/or modify 5 it under the terms of the GNU Lesser General Public License as 6 published by the Free Software Foundation; either version 3 of the 7 License, or (at your option) any later version. 8 9 This library is distributed in the hope that it will be useful, but 10 WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 Lesser General Public License for more details. 13 */ 14 15 /** 16 * Tools originally written for the BirdFont project. 17 */ 18 namespace Bird { 19 20 /** Log levels */ 21 internal const int NONE = 0; 22 internal const int WARNINGS = 1; 23 24 /** 25 * XML parser 26 * 27 * A tiny XML parser written in Vala. 28 * 29 * Example: 30 * {{{ 31 * 32 * // Print all tags and attributes in an XML document. 33 * // Expected output: 34 * // tag1 35 * // tag2 36 * // attribute1 37 * public static int main (string[] arg) { 38 * Tag root; 39 * XmlParser parser; 40 * 41 * parser = new XmlParser ("""<tag1><tag2 attribute1=""/></tag1>"""); 42 * 43 * if (parser.validate ()) { 44 * root = parser.get_root_tag (); 45 * print_tags (root); 46 * } 47 * } 48 * 49 * 50 * void print_tags (Tag tag) { 51 * print (tag.get_name ()); 52 * print ("\n"); 53 * print_attributes (tag); 54 * 55 * foreach (Tag t in tag) { 56 * print_tags (t); 57 * } 58 * } 59 * 60 * void print_attributes (Tag tag) { 61 * Attributes attributes = tag.get_attributes (); 62 * foreach (Attribute attribute in attributes) { 63 * print (attribute.get_name ()); 64 * print ("\n"); 65 * } 66 * } 67 * 68 * }}} 69 * 70 */ 71 public class XmlParser : GLib.Object { 72 public Tag root; 73 public XmlString data; 74 public string input; 75 public bool error; 76 public int refcount = 1; 77 78 /** 79 * Create a new xml parser. 80 * @param data valid xml data 81 */ 82 public XmlParser (string data) { 83 this.input = data; 84 this.data = new XmlString (data, data.length); 85 reparse (NONE); 86 } 87 88 /** 89 * Determine if the document can be parsed. 90 * @return true if the xml document is valid xml. 91 */ 92 public bool validate () { 93 reparse (NONE); 94 95 if (error) { 96 return false; 97 } 98 99 validate_tags (root); 100 101 reparse (NONE); 102 return !error; 103 } 104 105 void validate_tags (Tag tag) { 106 Attributes attributes = tag.get_attributes (); 107 108 foreach (Attribute a in attributes) { 109 if (tag.has_failed () || a.name.length == 0) { 110 error = true; 111 return; 112 } 113 } 114 115 foreach (Tag t in tag) { 116 if (tag.has_failed ()) { 117 error = true; 118 return; 119 } 120 121 validate_tags (t); 122 } 123 } 124 125 /** 126 * Obtain the root tag. 127 * @return the root tag. 128 */ 129 public Tag get_root_tag () { 130 reparse (WARNINGS); 131 return root; 132 } 133 134 /** 135 * Reset the parser and start from the beginning of the XML document. 136 */ 137 internal void reparse (int log_level) { 138 int root_index; 139 Tag container; 140 XmlString content; 141 142 error = false; 143 144 root_index = find_root_tag (); 145 if (root_index == -1) { 146 if (log_level == WARNINGS) { 147 XmlParser.warning ("No root tag found."); 148 } 149 error = true; 150 root = new Tag.empty (); 151 } else { 152 content = data.substring (root_index); 153 container = new Tag (new XmlString ("", 0), new XmlString ("", 0), content, log_level); 154 root = container.get_next_tag (); 155 } 156 } 157 158 int find_root_tag () { 159 int index = 0; 160 int prev_index = 0; 161 int modifier = 0; 162 unichar c; 163 164 while (true) { 165 prev_index = index; 166 if (!data.get_next_char (ref index, out c)) { 167 break; 168 } 169 170 if (c == '<') { 171 modifier = index; 172 data.get_next_char (ref modifier, out c); 173 if (c != '?' && c != '[' && c != '!') { 174 return prev_index; 175 } 176 } 177 } 178 179 return -1; 180 } 181 182 /** Print a warning message. */ 183 public static void warning (string message) { 184 print ("XML error: "); 185 print (message); 186 print ("\n"); 187 } 188 189 /** Replace escaped character with plain text characters. 190 * &amp; will be replaced with & etc. 191 */ 192 public static string decode (string s) { 193 string t; 194 t = s.replace ("&quot;", "\""); 195 t = t.replace ("&apos;;", "'"); 196 t = t.replace ("&lt;", "<"); 197 t = t.replace ("&gt;", ">"); 198 t = t.replace ("&amp;", "&"); 199 return t; 200 } 201 202 public static string encode (string s) { 203 string t; 204 t = s.replace ("\"", "&quot;"); 205 t = t.replace ("'", "&apos;;"); 206 t = t.replace ("<", "&lt;"); 207 t = t.replace (">", "&gt;"); 208 t = t.replace ("&", "&amp;"); 209 return t; 210 } 211 212 } 213 214 } 215