propane 3.1.0.pre-java → 3.2.0-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (104) hide show
  1. checksums.yaml +4 -4
  2. data/.mvn/wrapper/maven-wrapper.properties +1 -0
  3. data/CHANGELOG.md +1 -5
  4. data/README.md +23 -12
  5. data/Rakefile +23 -12
  6. data/lib/propane/helpers/version_error.rb +6 -0
  7. data/lib/propane/runner.rb +12 -0
  8. data/lib/propane/version.rb +1 -1
  9. data/library/slider/slider.rb +1 -1
  10. data/mvnw +234 -0
  11. data/mvnw.cmd +145 -0
  12. data/pom.xml +28 -27
  13. data/propane.gemspec +2 -2
  14. data/src/main/java/japplemenubar/JAppleMenuBar.java +41 -47
  15. data/src/main/java/monkstone/ColorUtil.java +1 -1
  16. data/src/main/java/monkstone/MathToolModule.java +12 -11
  17. data/src/main/java/monkstone/PropaneLibrary.java +9 -10
  18. data/src/main/java/monkstone/core/LibraryProxy.java +124 -113
  19. data/src/main/java/monkstone/fastmath/Deglut.java +86 -89
  20. data/src/main/java/monkstone/filechooser/Chooser.java +7 -13
  21. data/src/main/java/monkstone/noise/SimplexNoise.java +0 -1
  22. data/src/main/java/monkstone/slider/CustomHorizontalSlider.java +4 -4
  23. data/src/main/java/monkstone/slider/CustomVerticalSlider.java +1 -1
  24. data/src/main/java/monkstone/slider/SimpleHorizontalSlider.java +9 -9
  25. data/src/main/java/monkstone/slider/SimpleSlider.java +0 -9
  26. data/src/main/java/monkstone/slider/SimpleVerticalSlider.java +11 -13
  27. data/src/main/java/monkstone/slider/Slider.java +1 -1
  28. data/src/main/java/monkstone/slider/SliderBar.java +1 -1
  29. data/src/main/java/monkstone/slider/SliderGroup.java +1 -1
  30. data/src/main/java/monkstone/slider/WheelHandler.java +8 -9
  31. data/src/main/java/monkstone/vecmath/AppRender.java +2 -2
  32. data/src/main/java/monkstone/vecmath/ShapeRender.java +2 -2
  33. data/src/main/java/monkstone/vecmath/package-info.java +2 -2
  34. data/src/main/java/monkstone/vecmath/vec2/Vec2.java +2 -2
  35. data/src/main/java/monkstone/vecmath/vec3/Vec3.java +1 -1
  36. data/src/main/java/monkstone/videoevent/VideoInterface.java +11 -5
  37. data/src/main/java/monkstone/videoevent/package-info.java +2 -2
  38. data/src/main/java/processing/awt/PGraphicsJava2D.java +1742 -2243
  39. data/src/main/java/processing/awt/PShapeJava2D.java +268 -270
  40. data/src/main/java/processing/awt/PSurfaceAWT.java +821 -920
  41. data/src/main/java/processing/core/DesktopHandler.java +94 -0
  42. data/src/main/java/processing/core/PApplet.java +14170 -14082
  43. data/src/main/java/processing/core/PConstants.java +447 -473
  44. data/src/main/java/processing/core/PFont.java +867 -873
  45. data/src/main/java/processing/core/PGraphics.java +7193 -7428
  46. data/src/main/java/processing/core/PImage.java +3051 -3117
  47. data/src/main/java/processing/core/PMatrix.java +159 -172
  48. data/src/main/java/processing/core/PMatrix2D.java +403 -444
  49. data/src/main/java/processing/core/PMatrix3D.java +735 -749
  50. data/src/main/java/processing/core/PShape.java +2651 -2793
  51. data/src/main/java/processing/core/PShapeOBJ.java +415 -422
  52. data/src/main/java/processing/core/PShapeSVG.java +1466 -1475
  53. data/src/main/java/processing/core/PStyle.java +37 -40
  54. data/src/main/java/processing/core/PSurface.java +98 -103
  55. data/src/main/java/processing/core/PSurfaceNone.java +208 -236
  56. data/src/main/java/processing/core/PVector.java +961 -990
  57. data/src/main/java/processing/data/DoubleDict.java +709 -753
  58. data/src/main/java/processing/data/DoubleList.java +695 -748
  59. data/src/main/java/processing/data/FloatDict.java +702 -746
  60. data/src/main/java/processing/data/FloatList.java +697 -751
  61. data/src/main/java/processing/data/IntDict.java +673 -718
  62. data/src/main/java/processing/data/IntList.java +633 -699
  63. data/src/main/java/processing/data/JSONArray.java +873 -931
  64. data/src/main/java/processing/data/JSONObject.java +1165 -1262
  65. data/src/main/java/processing/data/JSONTokener.java +341 -351
  66. data/src/main/java/processing/data/LongDict.java +662 -707
  67. data/src/main/java/processing/data/LongList.java +634 -700
  68. data/src/main/java/processing/data/Sort.java +41 -37
  69. data/src/main/java/processing/data/StringDict.java +486 -522
  70. data/src/main/java/processing/data/StringList.java +580 -624
  71. data/src/main/java/processing/data/Table.java +3508 -3686
  72. data/src/main/java/processing/data/TableRow.java +183 -182
  73. data/src/main/java/processing/data/XML.java +883 -957
  74. data/src/main/java/processing/event/Event.java +66 -87
  75. data/src/main/java/processing/event/KeyEvent.java +41 -48
  76. data/src/main/java/processing/event/MouseEvent.java +93 -103
  77. data/src/main/java/processing/event/TouchEvent.java +6 -10
  78. data/src/main/java/processing/javafx/PGraphicsFX2D.java +5 -69
  79. data/src/main/java/processing/javafx/PSurfaceFX.java +2 -7
  80. data/src/main/java/processing/opengl/FontTexture.java +270 -290
  81. data/src/main/java/processing/opengl/FrameBuffer.java +363 -375
  82. data/src/main/java/processing/opengl/LinePath.java +500 -543
  83. data/src/main/java/processing/opengl/LineStroker.java +582 -593
  84. data/src/main/java/processing/opengl/PGL.java +2881 -2904
  85. data/src/main/java/processing/opengl/PGraphics2D.java +315 -408
  86. data/src/main/java/processing/opengl/PGraphics3D.java +72 -107
  87. data/src/main/java/processing/opengl/PGraphicsOpenGL.java +12043 -12230
  88. data/src/main/java/processing/opengl/PJOGL.java +1681 -1745
  89. data/src/main/java/processing/opengl/PShader.java +1257 -1260
  90. data/src/main/java/processing/opengl/PShapeOpenGL.java +4599 -4662
  91. data/src/main/java/processing/opengl/PSurfaceJOGL.java +1030 -1047
  92. data/src/main/java/processing/opengl/Texture.java +1397 -1462
  93. data/src/main/java/processing/opengl/VertexBuffer.java +55 -57
  94. data/src/main/resources/icon/icon-1024.png +0 -0
  95. data/src/main/resources/icon/icon-128.png +0 -0
  96. data/src/main/resources/icon/icon-16.png +0 -0
  97. data/src/main/resources/icon/icon-256.png +0 -0
  98. data/src/main/resources/icon/icon-32.png +0 -0
  99. data/src/main/resources/icon/icon-48.png +0 -0
  100. data/src/main/resources/icon/icon-512.png +0 -0
  101. data/src/main/resources/icon/icon-64.png +0 -0
  102. data/vendors/Rakefile +1 -1
  103. metadata +12 -8
  104. data/src/main/java/processing/core/ThinkDifferent.java +0 -70
@@ -13,186 +13,187 @@ import java.io.PrintWriter;
13
13
  */
14
14
  public interface TableRow {
15
15
 
16
- /**
17
- * @webref tablerow:method
18
- * @brief Get an String value from the specified column
19
- * @param column ID number of the column to reference
20
- * @see TableRow#getInt(int)
21
- * @see TableRow#getFloat(int)
22
- */
23
- public String getString(int column);
24
-
25
- /**
26
- * @param columnName title of the column to reference
27
- */
28
- public String getString(String columnName);
29
-
30
- /**
31
- * @webref tablerow:method
32
- * @brief Get an integer value from the specified column
33
- * @param column ID number of the column to reference
34
- * @see TableRow#getFloat(int)
35
- * @see TableRow#getString(int)
36
- */
37
- public int getInt(int column);
38
-
39
- /**
40
- * @param columnName title of the column to reference
41
- */
42
- public int getInt(String columnName);
43
-
44
- /**
45
- * @brief Get a long value from the specified column
46
- * @param column ID number of the column to reference
47
- * @see TableRow#getFloat(int)
48
- * @see TableRow#getString(int)
49
- */
50
-
51
- public long getLong(int column);
52
-
53
- /**
54
- * @param columnName title of the column to reference
55
- */
56
- public long getLong(String columnName);
57
-
58
- /**
59
- * @webref tablerow:method
60
- * @brief Get a float value from the specified column
61
- * @param column ID number of the column to reference
62
- * @see TableRow#getInt(int)
63
- * @see TableRow#getString(int)
64
- */
65
- public float getFloat(int column);
66
-
67
- /**
68
- * @param columnName title of the column to reference
69
- */
70
- public float getFloat(String columnName);
71
-
72
- /**
73
- * @brief Get a double value from the specified column
74
- * @param column ID number of the column to reference
75
- * @see TableRow#getInt(int)
76
- * @see TableRow#getString(int)
77
- */
78
- public double getDouble(int column);
79
-
80
- /**
81
- * @param columnName title of the column to reference
82
- */
83
- public double getDouble(String columnName);
84
-
85
- /**
86
- * @webref tablerow:method
87
- * @brief Store a String value in the specified column
88
- * @param column ID number of the target column
89
- * @param value value to assign
90
- * @see TableRow#setInt(int, int)
91
- * @see TableRow#setFloat(int, float)
92
- */
93
- public void setString(int column, String value);
94
- /**
95
- * @param columnName title of the target column
96
- */
97
- public void setString(String columnName, String value);
98
-
99
- /**
100
- * @webref tablerow:method
101
- * @brief Store an integer value in the specified column
102
- * @param column ID number of the target column
103
- * @param value value to assign
104
- * @see TableRow#setFloat(int, float)
105
- * @see TableRow#setString(int, String)
106
- */
107
- public void setInt(int column, int value);
108
-
109
- /**
110
- * @param columnName title of the target column
111
- */
112
- public void setInt(String columnName, int value);
113
-
114
- /**
115
- * @brief Store a long value in the specified column
116
- * @param column ID number of the target column
117
- * @param value value to assign
118
- * @see TableRow#setFloat(int, float)
119
- * @see TableRow#setString(int, String)
120
- */
121
- public void setLong(int column, long value);
122
-
123
- /**
124
- * @param columnName title of the target column
125
- */
126
- public void setLong(String columnName, long value);
127
-
128
- /**
129
- * @webref tablerow:method
130
- * @brief Store a float value in the specified column
131
- * @param column ID number of the target column
132
- * @param value value to assign
133
- * @see TableRow#setInt(int, int)
134
- * @see TableRow#setString(int, String)
135
- */
136
- public void setFloat(int column, float value);
137
-
138
- /**
139
- * @param columnName title of the target column
140
- */
141
- public void setFloat(String columnName, float value);
142
-
143
- /**
144
- * @brief Store a double value in the specified column
145
- * @param column ID number of the target column
146
- * @param value value to assign
147
- * @see TableRow#setFloat(int, float)
148
- * @see TableRow#setString(int, String)
149
- */
150
- public void setDouble(int column, double value);
151
-
152
- /**
153
- * @param columnName title of the target column
154
- */
155
- public void setDouble(String columnName, double value);
156
-
157
- /**
158
- * @webref tablerow:method
159
- * @brief Get the column count.
160
- * @return count of all columns
161
- */
162
- public int getColumnCount();
163
-
164
- /**
165
- * @brief Get the column type.
166
- * @param columnName title of the target column
167
- * @return type of the column
168
- */
169
- public int getColumnType(String columnName);
170
-
171
- /**
172
- * @param column ID number of the target column
173
- */
174
- public int getColumnType(int column);
175
-
176
- /**
177
- * @brief Get the all column types
178
- * @return list of all column types
179
- */
180
- public int[] getColumnTypes();
181
-
182
- /**
183
- * @webref tablerow:method
184
- * @brief Get the column title.
185
- * @param column ID number of the target column
186
- * @return title of the column
187
- */
188
- public String getColumnTitle(int column);
189
-
190
- /**
191
- * @brief Get the all column titles
192
- * @return list of all column titles
193
- */
194
- public String[] getColumnTitles();
195
-
196
- public void write(PrintWriter writer);
197
- public void print();
16
+ /**
17
+ * @webref tablerow:method
18
+ * @brief Get an String value from the specified column
19
+ * @param column ID number of the column to reference
20
+ * @see TableRow#getInt(int)
21
+ * @see TableRow#getFloat(int)
22
+ */
23
+ public String getString(int column);
24
+
25
+ /**
26
+ * @param columnName title of the column to reference
27
+ */
28
+ public String getString(String columnName);
29
+
30
+ /**
31
+ * @webref tablerow:method
32
+ * @brief Get an integer value from the specified column
33
+ * @param column ID number of the column to reference
34
+ * @see TableRow#getFloat(int)
35
+ * @see TableRow#getString(int)
36
+ */
37
+ public int getInt(int column);
38
+
39
+ /**
40
+ * @param columnName title of the column to reference
41
+ */
42
+ public int getInt(String columnName);
43
+
44
+ /**
45
+ * @brief Get a long value from the specified column
46
+ * @param column ID number of the column to reference
47
+ * @see TableRow#getFloat(int)
48
+ * @see TableRow#getString(int)
49
+ */
50
+ public long getLong(int column);
51
+
52
+ /**
53
+ * @param columnName title of the column to reference
54
+ */
55
+ public long getLong(String columnName);
56
+
57
+ /**
58
+ * @webref tablerow:method
59
+ * @brief Get a float value from the specified column
60
+ * @param column ID number of the column to reference
61
+ * @see TableRow#getInt(int)
62
+ * @see TableRow#getString(int)
63
+ */
64
+ public float getFloat(int column);
65
+
66
+ /**
67
+ * @param columnName title of the column to reference
68
+ */
69
+ public float getFloat(String columnName);
70
+
71
+ /**
72
+ * @brief Get a double value from the specified column
73
+ * @param column ID number of the column to reference
74
+ * @see TableRow#getInt(int)
75
+ * @see TableRow#getString(int)
76
+ */
77
+ public double getDouble(int column);
78
+
79
+ /**
80
+ * @param columnName title of the column to reference
81
+ */
82
+ public double getDouble(String columnName);
83
+
84
+ /**
85
+ * @webref tablerow:method
86
+ * @brief Store a String value in the specified column
87
+ * @param column ID number of the target column
88
+ * @param value value to assign
89
+ * @see TableRow#setInt(int, int)
90
+ * @see TableRow#setFloat(int, float)
91
+ */
92
+ public void setString(int column, String value);
93
+
94
+ /**
95
+ * @param columnName title of the target column
96
+ */
97
+ public void setString(String columnName, String value);
98
+
99
+ /**
100
+ * @webref tablerow:method
101
+ * @brief Store an integer value in the specified column
102
+ * @param column ID number of the target column
103
+ * @param value value to assign
104
+ * @see TableRow#setFloat(int, float)
105
+ * @see TableRow#setString(int, String)
106
+ */
107
+ public void setInt(int column, int value);
108
+
109
+ /**
110
+ * @param columnName title of the target column
111
+ */
112
+ public void setInt(String columnName, int value);
113
+
114
+ /**
115
+ * @brief Store a long value in the specified column
116
+ * @param column ID number of the target column
117
+ * @param value value to assign
118
+ * @see TableRow#setFloat(int, float)
119
+ * @see TableRow#setString(int, String)
120
+ */
121
+ public void setLong(int column, long value);
122
+
123
+ /**
124
+ * @param columnName title of the target column
125
+ */
126
+ public void setLong(String columnName, long value);
127
+
128
+ /**
129
+ * @webref tablerow:method
130
+ * @brief Store a float value in the specified column
131
+ * @param column ID number of the target column
132
+ * @param value value to assign
133
+ * @see TableRow#setInt(int, int)
134
+ * @see TableRow#setString(int, String)
135
+ */
136
+ public void setFloat(int column, float value);
137
+
138
+ /**
139
+ * @param columnName title of the target column
140
+ */
141
+ public void setFloat(String columnName, float value);
142
+
143
+ /**
144
+ * @brief Store a double value in the specified column
145
+ * @param column ID number of the target column
146
+ * @param value value to assign
147
+ * @see TableRow#setFloat(int, float)
148
+ * @see TableRow#setString(int, String)
149
+ */
150
+ public void setDouble(int column, double value);
151
+
152
+ /**
153
+ * @param columnName title of the target column
154
+ */
155
+ public void setDouble(String columnName, double value);
156
+
157
+ /**
158
+ * @webref tablerow:method
159
+ * @brief Get the column count.
160
+ * @return count of all columns
161
+ */
162
+ public int getColumnCount();
163
+
164
+ /**
165
+ * @brief Get the column type.
166
+ * @param columnName title of the target column
167
+ * @return type of the column
168
+ */
169
+ public int getColumnType(String columnName);
170
+
171
+ /**
172
+ * @param column ID number of the target column
173
+ */
174
+ public int getColumnType(int column);
175
+
176
+ /**
177
+ * @brief Get the all column types
178
+ * @return list of all column types
179
+ */
180
+ public int[] getColumnTypes();
181
+
182
+ /**
183
+ * @webref tablerow:method
184
+ * @brief Get the column title.
185
+ * @param column ID number of the target column
186
+ * @return title of the column
187
+ */
188
+ public String getColumnTitle(int column);
189
+
190
+ /**
191
+ * @brief Get the all column titles
192
+ * @return list of all column titles
193
+ */
194
+ public String[] getColumnTitles();
195
+
196
+ public void write(PrintWriter writer);
197
+
198
+ public void print();
198
199
  }
@@ -1,5 +1,3 @@
1
- /* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
2
-
3
1
  /*
4
2
  Part of the Processing project - http://processing.org
5
3
 
@@ -19,8 +17,7 @@
19
17
  Public License along with this library; if not, write to the
20
18
  Free Software Foundation, Inc., 59 Temple Place, Suite 330,
21
19
  Boston, MA 02111-1307 USA
22
- */
23
-
20
+ */
24
21
  package processing.data;
25
22
 
26
23
  import java.io.*;
@@ -39,10 +36,9 @@ import javax.xml.xpath.XPathFactory;
39
36
 
40
37
  import processing.core.PApplet;
41
38
 
42
-
43
39
  /**
44
- * This is the base class used for the Processing XML library,
45
- * representing a single node of an XML tree.
40
+ * This is the base class used for the Processing XML library, representing a
41
+ * single node of an XML tree.
46
42
  *
47
43
  * @webref data:composite
48
44
  * @see PApplet#loadXML(String)
@@ -51,23 +47,28 @@ import processing.core.PApplet;
51
47
  */
52
48
  public class XML implements Serializable {
53
49
 
54
- /** The internal representation, a DOM node. */
55
- protected Node node;
50
+ /**
51
+ * The internal representation, a DOM node.
52
+ */
53
+ protected Node node;
56
54
 
57
55
  // /** Cached locally because it's used often. */
58
56
  // protected String name;
59
-
60
- /** The parent element. */
61
- protected XML parent;
62
-
63
- /** Child elements, once loaded. */
64
- protected XML[] children;
65
-
66
- /**
67
- * @nowebref
68
- */
69
- protected XML() { }
70
-
57
+ /**
58
+ * The parent element.
59
+ */
60
+ protected XML parent;
61
+
62
+ /**
63
+ * Child elements, once loaded.
64
+ */
65
+ protected XML[] children;
66
+
67
+ /**
68
+ * @nowebref
69
+ */
70
+ protected XML() {
71
+ }
71
72
 
72
73
  // /**
73
74
  // * Begin parsing XML data passed in from a PApplet. This code
@@ -81,324 +82,301 @@ public class XML implements Serializable {
81
82
  // public XML(PApplet parent, String filename) throws IOException, ParserConfigurationException, SAXException {
82
83
  // this(parent.createReader(filename));
83
84
  // }
85
+ /**
86
+ * Advanced users only; use loadXML() in PApplet. This is not a supported
87
+ * function and is subject to change. It is available simply for users that
88
+ * would like to handle the exceptions in a particular way.
89
+ *
90
+ * @nowebref
91
+ */
92
+ public XML(File file) throws IOException, ParserConfigurationException, SAXException {
93
+ this(file, null);
94
+ }
84
95
 
96
+ /**
97
+ * Advanced users only; use loadXML() in PApplet.
98
+ *
99
+ * @nowebref
100
+ */
101
+ public XML(File file, String options) throws IOException, ParserConfigurationException, SAXException {
102
+ this(PApplet.createReader(file), options);
103
+ }
85
104
 
86
- /**
87
- * Advanced users only; use loadXML() in PApplet. This is not a supported
88
- * function and is subject to change. It is available simply for users that
89
- * would like to handle the exceptions in a particular way.
90
- *
91
- * @nowebref
92
- */
93
- public XML(File file) throws IOException, ParserConfigurationException, SAXException {
94
- this(file, null);
95
- }
96
-
97
-
98
- /**
99
- * Advanced users only; use loadXML() in PApplet.
100
- *
101
- * @nowebref
102
- */
103
- public XML(File file, String options) throws IOException, ParserConfigurationException, SAXException {
104
- this(PApplet.createReader(file), options);
105
- }
106
-
107
- /**
108
- * @nowebref
109
- */
110
- public XML(InputStream input) throws IOException, ParserConfigurationException, SAXException {
111
- this(input, null);
112
- }
113
-
114
-
115
- /**
116
- * Unlike the loadXML() method in PApplet, this version works with files
117
- * that are not in UTF-8 format.
118
- *
119
- * @nowebref
120
- */
121
- public XML(InputStream input, String options) throws IOException, ParserConfigurationException, SAXException {
122
- //this(PApplet.createReader(input), options); // won't handle non-UTF8
123
- DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
124
-
125
- try {
126
- // Prevent 503 errors from www.w3.org
127
- factory.setAttribute("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
128
- } catch (IllegalArgumentException e) {
129
- // ignore this; Android doesn't like it
130
- }
131
-
132
- factory.setExpandEntityReferences(false);
133
- DocumentBuilder builder = factory.newDocumentBuilder();
134
- Document document = builder.parse(new InputSource(input));
135
- node = document.getDocumentElement();
136
- }
137
-
138
-
139
- /**
140
- * Advanced users only; use loadXML() in PApplet.
141
- *
142
- * @nowebref
143
- */
144
- public XML(Reader reader) throws IOException, ParserConfigurationException, SAXException {
145
- this(reader, null);
146
- }
147
-
148
-
149
- /**
150
- * Advanced users only; use loadXML() in PApplet.
151
- *
152
- * Added extra code to handle \u2028 (Unicode NLF), which is sometimes
153
- * inserted by web browsers (Safari?) and not distinguishable from a "real"
154
- * LF (or CRLF) in some text editors (i.e. TextEdit on OS X). Only doing
155
- * this for XML (and not all Reader objects) because LFs are essential.
156
- * https://github.com/processing/processing/issues/2100
157
- *
158
- * @nowebref
159
- */
160
- public XML(final Reader reader, String options) throws IOException, ParserConfigurationException, SAXException {
161
- DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
162
-
163
- // Prevent 503 errors from www.w3.org
164
- try {
165
- factory.setAttribute("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
166
- } catch (IllegalArgumentException e) {
167
- // ignore this; Android doesn't like it
168
- }
169
-
170
- // without a validating DTD, this doesn't do anything since it doesn't know what is ignorable
171
- // factory.setIgnoringElementContentWhitespace(true);
105
+ /**
106
+ * @nowebref
107
+ */
108
+ public XML(InputStream input) throws IOException, ParserConfigurationException, SAXException {
109
+ this(input, null);
110
+ }
111
+
112
+ /**
113
+ * Unlike the loadXML() method in PApplet, this version works with files
114
+ * that are not in UTF-8 format.
115
+ *
116
+ * @nowebref
117
+ */
118
+ public XML(InputStream input, String options) throws IOException, ParserConfigurationException, SAXException {
119
+ //this(PApplet.createReader(input), options); // won't handle non-UTF8
120
+ DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
121
+
122
+ try {
123
+ // Prevent 503 errors from www.w3.org
124
+ factory.setAttribute("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
125
+ } catch (IllegalArgumentException e) {
126
+ // ignore this; Android doesn't like it
127
+ }
128
+
129
+ factory.setExpandEntityReferences(false);
130
+ DocumentBuilder builder = factory.newDocumentBuilder();
131
+ Document document = builder.parse(new InputSource(input));
132
+ node = document.getDocumentElement();
133
+ }
134
+
135
+ /**
136
+ * Advanced users only; use loadXML() in PApplet.
137
+ *
138
+ * @nowebref
139
+ */
140
+ public XML(Reader reader) throws IOException, ParserConfigurationException, SAXException {
141
+ this(reader, null);
142
+ }
143
+
144
+ /**
145
+ * Advanced users only; use loadXML() in PApplet.
146
+ *
147
+ * Added extra code to handle \u2028 (Unicode NLF), which is sometimes
148
+ * inserted by web browsers (Safari?) and not distinguishable from a "real"
149
+ * LF (or CRLF) in some text editors (i.e. TextEdit on OS X). Only doing
150
+ * this for XML (and not all Reader objects) because LFs are essential.
151
+ * https://github.com/processing/processing/issues/2100
152
+ *
153
+ * @nowebref
154
+ */
155
+ public XML(final Reader reader, String options) throws IOException, ParserConfigurationException, SAXException {
156
+ DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
157
+
158
+ // Prevent 503 errors from www.w3.org
159
+ try {
160
+ factory.setAttribute("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
161
+ } catch (IllegalArgumentException e) {
162
+ // ignore this; Android doesn't like it
163
+ }
172
164
 
173
- factory.setExpandEntityReferences(false);
165
+ // without a validating DTD, this doesn't do anything since it doesn't know what is ignorable
166
+ // factory.setIgnoringElementContentWhitespace(true);
167
+ factory.setExpandEntityReferences(false);
174
168
  // factory.setExpandEntityReferences(true);
175
169
 
176
170
  // factory.setCoalescing(true);
177
171
  // builderFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
178
- DocumentBuilder builder = factory.newDocumentBuilder();
172
+ DocumentBuilder builder = factory.newDocumentBuilder();
179
173
  // builder.setEntityResolver()
180
174
 
181
175
  // SAXParserFactory spf = SAXParserFactory.newInstance();
182
176
  // spf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
183
177
  // SAXParser p = spf.newSAXParser();
178
+ // builder = DocumentBuilderFactory.newDocumentBuilder();
179
+ // builder = new SAXBuilder();
180
+ // builder.setValidation(validating);
181
+ Document document = builder.parse(new InputSource(new Reader() {
182
+ @Override
183
+ public int read(char[] cbuf, int off, int len) throws IOException {
184
+ int count = reader.read(cbuf, off, len);
185
+ for (int i = 0; i < count; i++) {
186
+ if (cbuf[off + i] == '\u2028') {
187
+ cbuf[off + i] = '\n';
188
+ }
189
+ }
190
+ return count;
191
+ }
192
+
193
+ @Override
194
+ public void close() throws IOException {
195
+ reader.close();
196
+ }
197
+ }));
198
+ node = document.getDocumentElement();
199
+ }
184
200
 
185
- // builder = DocumentBuilderFactory.newDocumentBuilder();
186
- // builder = new SAXBuilder();
187
- // builder.setValidation(validating);
188
-
189
- Document document = builder.parse(new InputSource(new Reader() {
190
- @Override
191
- public int read(char[] cbuf, int off, int len) throws IOException {
192
- int count = reader.read(cbuf, off, len);
193
- for (int i = 0; i < count; i++) {
194
- if (cbuf[off+i] == '\u2028') {
195
- cbuf[off+i] = '\n';
196
- }
197
- }
198
- return count;
199
- }
200
-
201
- @Override
202
- public void close() throws IOException {
203
- reader.close();
204
- }
205
- }));
206
- node = document.getDocumentElement();
207
- }
208
-
209
-
210
- /**
211
- * @param name creates a node with this name
212
- *
213
- */
214
- public XML(String name) {
215
- try {
216
- // TODO is there a more efficient way of doing this? wow.
217
- DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
218
- DocumentBuilder builder = factory.newDocumentBuilder();
219
- Document document = builder.newDocument();
220
- node = document.createElement(name);
221
- this.parent = null;
222
-
223
- } catch (ParserConfigurationException pce) {
224
- throw new RuntimeException(pce);
225
- }
226
- }
227
-
228
- /**
229
- * @nowebref
230
- */
231
- protected XML(XML parent, Node node) {
232
- this.node = node;
233
- this.parent = parent;
234
-
235
- for (String attr : parent.listAttributes()) {
236
- if (attr.startsWith("xmlns")) {
237
- // Copy namespace attributes to the kids, otherwise this XML
238
- // can no longer be printed (or manipulated in most ways).
239
- // Only do this when it's an Element, otherwise it's trying to set
240
- // attributes on text notes (interstitial content).
241
- if (node instanceof Element) {
242
- setString(attr, parent.getString(attr));
201
+ /**
202
+ * @param name creates a node with this name
203
+ *
204
+ */
205
+ public XML(String name) {
206
+ try {
207
+ // TODO is there a more efficient way of doing this? wow.
208
+ DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
209
+ DocumentBuilder builder = factory.newDocumentBuilder();
210
+ Document document = builder.newDocument();
211
+ node = document.createElement(name);
212
+ this.parent = null;
213
+
214
+ } catch (ParserConfigurationException pce) {
215
+ throw new RuntimeException(pce);
243
216
  }
244
- }
245
217
  }
246
- }
247
218
 
219
+ /**
220
+ * @nowebref
221
+ */
222
+ protected XML(XML parent, Node node) {
223
+ this.node = node;
224
+ this.parent = parent;
225
+
226
+ for (String attr : parent.listAttributes()) {
227
+ if (attr.startsWith("xmlns")) {
228
+ // Copy namespace attributes to the kids, otherwise this XML
229
+ // can no longer be printed (or manipulated in most ways).
230
+ // Only do this when it's an Element, otherwise it's trying to set
231
+ // attributes on text notes (interstitial content).
232
+ if (node instanceof Element) {
233
+ setString(attr, parent.getString(attr));
234
+ }
235
+ }
236
+ }
237
+ }
248
238
 
249
- /**
250
- * @webref xml:method
251
- * @brief Converts String content to an XML object
252
- * @param data the content to be parsed as XML
253
- * @return an XML object, or null
254
- * @throws SAXException
255
- * @throws ParserConfigurationException
256
- * @throws IOException
257
- * @nowebref
258
- */
259
- static public XML parse(String data) throws IOException, ParserConfigurationException, SAXException {
260
- return XML.parse(data, null);
261
- }
262
-
263
- /**
264
- * @nowebref
265
- */
266
- static public XML parse(String data, String options) throws IOException, ParserConfigurationException, SAXException {
267
- return new XML(new StringReader(data), null);
268
- }
239
+ /**
240
+ * @webref xml:method
241
+ * @brief Converts String content to an XML object
242
+ * @param data the content to be parsed as XML
243
+ * @return an XML object, or null
244
+ * @throws SAXException
245
+ * @throws ParserConfigurationException
246
+ * @throws IOException
247
+ * @nowebref
248
+ */
249
+ static public XML parse(String data) throws IOException, ParserConfigurationException, SAXException {
250
+ return XML.parse(data, null);
251
+ }
269
252
 
253
+ /**
254
+ * @nowebref
255
+ */
256
+ static public XML parse(String data, String options) throws IOException, ParserConfigurationException, SAXException {
257
+ return new XML(new StringReader(data), null);
258
+ }
270
259
 
271
260
  // protected boolean save(OutputStream output) {
272
261
  // return write(PApplet.createWriter(output));
273
262
  // }
263
+ public boolean save(File file) {
264
+ return save(file, null);
265
+ }
266
+
267
+ public boolean save(File file, String options) {
268
+ PrintWriter writer = PApplet.createWriter(file);
269
+ boolean result = write(writer);
270
+ writer.flush();
271
+ writer.close();
272
+ return result;
273
+ }
274
274
 
275
+ // Sends this object and its kids to a Writer with an indent of 2 spaces,
276
+ // including the declaration at the top so that the output will be valid XML.
277
+ public boolean write(PrintWriter output) {
278
+ output.print(format(2));
279
+ output.flush();
280
+ return true;
281
+ }
275
282
 
276
- public boolean save(File file) {
277
- return save(file, null);
278
- }
279
-
280
-
281
- public boolean save(File file, String options) {
282
- PrintWriter writer = PApplet.createWriter(file);
283
- boolean result = write(writer);
284
- writer.flush();
285
- writer.close();
286
- return result;
287
- }
288
-
289
-
290
- // Sends this object and its kids to a Writer with an indent of 2 spaces,
291
- // including the declaration at the top so that the output will be valid XML.
292
- public boolean write(PrintWriter output) {
293
- output.print(format(2));
294
- output.flush();
295
- return true;
296
- }
297
-
298
-
299
- /**
300
- * Returns the parent element. This method returns null for the root
301
- * element.
302
- *
303
- * @webref xml:method
304
- * @brief Gets a copy of the element's parent
305
- */
306
- public XML getParent() {
307
- return this.parent;
308
- }
309
-
310
- /**
311
- * Internal function; not included in reference.
312
- */
313
- protected Object getNative() {
314
- return node;
315
- }
316
-
317
-
318
- /**
319
- * Returns the full name (i.e. the name including an eventual namespace
320
- * prefix) of the element.
321
- *
322
- * @webref xml:method
323
- * @brief Gets the element's full name
324
- * @return the name, or null if the element only contains #PCDATA.
325
- */
326
- public String getName() {
283
+ /**
284
+ * Returns the parent element. This method returns null for the root
285
+ * element.
286
+ *
287
+ * @webref xml:method
288
+ * @brief Gets a copy of the element's parent
289
+ */
290
+ public XML getParent() {
291
+ return this.parent;
292
+ }
293
+
294
+ /**
295
+ * Internal function; not included in reference.
296
+ */
297
+ protected Object getNative() {
298
+ return node;
299
+ }
300
+
301
+ /**
302
+ * Returns the full name (i.e. the name including an eventual namespace
303
+ * prefix) of the element.
304
+ *
305
+ * @webref xml:method
306
+ * @brief Gets the element's full name
307
+ * @return the name, or null if the element only contains #PCDATA.
308
+ */
309
+ public String getName() {
327
310
  // return name;
328
- return node.getNodeName();
329
- }
330
-
331
- /**
332
- * @webref xml:method
333
- * @brief Sets the element's name
334
- */
335
- public void setName(String newName) {
336
- Document document = node.getOwnerDocument();
337
- node = document.renameNode(node, null, newName);
311
+ return node.getNodeName();
312
+ }
313
+
314
+ /**
315
+ * @webref xml:method
316
+ * @brief Sets the element's name
317
+ */
318
+ public void setName(String newName) {
319
+ Document document = node.getOwnerDocument();
320
+ node = document.renameNode(node, null, newName);
338
321
  // name = node.getNodeName();
339
- }
340
-
341
-
342
- /**
343
- * Returns the name of the element (without namespace prefix).
344
- *
345
- * Internal function; not included in reference.
346
- */
347
- public String getLocalName() {
348
- return node.getLocalName();
349
- }
350
-
351
-
352
- /**
353
- * Honey, can you just check on the kids? Thanks.
354
- *
355
- * Internal function; not included in reference.
356
- */
357
- protected void checkChildren() {
358
- if (children == null) {
359
- NodeList kids = node.getChildNodes();
360
- int childCount = kids.getLength();
361
- children = new XML[childCount];
362
- for (int i = 0; i < childCount; i++) {
363
- children[i] = new XML(this, kids.item(i));
364
- }
365
- }
366
- }
367
-
368
-
369
- /**
370
- * Returns the number of children.
371
- *
372
- * @webref xml:method
373
- * @brief Returns the element's number of children
374
- * @return the count.
375
- */
376
- public int getChildCount() {
377
- checkChildren();
378
- return children.length;
379
- }
380
-
381
-
382
- /**
383
- * Returns a boolean of whether or not there are children.
384
- *
385
- * @webref xml:method
386
- * @brief Checks whether or not an element has any children
387
- */
388
- public boolean hasChildren() {
389
- checkChildren();
390
- return children.length > 0;
391
- }
392
-
393
-
394
- /**
395
- * Put the names of all children into an array. Same as looping through
396
- * each child and calling getName() on each XMLElement.
397
- *
398
- * @webref xml:method
399
- * @brief Returns the names of all children as an array
400
- */
401
- public String[] listChildren() {
322
+ }
323
+
324
+ /**
325
+ * Returns the name of the element (without namespace prefix).
326
+ *
327
+ * Internal function; not included in reference.
328
+ */
329
+ public String getLocalName() {
330
+ return node.getLocalName();
331
+ }
332
+
333
+ /**
334
+ * Honey, can you just check on the kids? Thanks.
335
+ *
336
+ * Internal function; not included in reference.
337
+ */
338
+ protected void checkChildren() {
339
+ if (children == null) {
340
+ NodeList kids = node.getChildNodes();
341
+ int childCount = kids.getLength();
342
+ children = new XML[childCount];
343
+ for (int i = 0; i < childCount; i++) {
344
+ children[i] = new XML(this, kids.item(i));
345
+ }
346
+ }
347
+ }
348
+
349
+ /**
350
+ * Returns the number of children.
351
+ *
352
+ * @webref xml:method
353
+ * @brief Returns the element's number of children
354
+ * @return the count.
355
+ */
356
+ public int getChildCount() {
357
+ checkChildren();
358
+ return children.length;
359
+ }
360
+
361
+ /**
362
+ * Returns a boolean of whether or not there are children.
363
+ *
364
+ * @webref xml:method
365
+ * @brief Checks whether or not an element has any children
366
+ */
367
+ public boolean hasChildren() {
368
+ checkChildren();
369
+ return children.length > 0;
370
+ }
371
+
372
+ /**
373
+ * Put the names of all children into an array. Same as looping through each
374
+ * child and calling getName() on each XMLElement.
375
+ *
376
+ * @webref xml:method
377
+ * @brief Returns the names of all children as an array
378
+ */
379
+ public String[] listChildren() {
402
380
  // NodeList children = node.getChildNodes();
403
381
  // int childCount = children.getLength();
404
382
  // String[] outgoing = new String[childCount];
@@ -408,22 +386,21 @@ public class XML implements Serializable {
408
386
  // outgoing[i] = kid.getNodeName();
409
387
  // } // otherwise just leave him null
410
388
  // }
411
- checkChildren();
412
- String[] outgoing = new String[children.length];
413
- for (int i = 0; i < children.length; i++) {
414
- outgoing[i] = children[i].getName();
415
- }
416
- return outgoing;
417
- }
418
-
419
-
420
- /**
421
- * Returns an array containing all the child elements.
422
- *
423
- * @webref xml:method
424
- * @brief Returns an array containing all child elements
425
- */
426
- public XML[] getChildren() {
389
+ checkChildren();
390
+ String[] outgoing = new String[children.length];
391
+ for (int i = 0; i < children.length; i++) {
392
+ outgoing[i] = children[i].getName();
393
+ }
394
+ return outgoing;
395
+ }
396
+
397
+ /**
398
+ * Returns an array containing all the child elements.
399
+ *
400
+ * @webref xml:method
401
+ * @brief Returns an array containing all child elements
402
+ */
403
+ public XML[] getChildren() {
427
404
  // NodeList children = node.getChildNodes();
428
405
  // int childCount = children.getLength();
429
406
  // XMLElement[] kids = new XMLElement[childCount];
@@ -432,194 +409,185 @@ public class XML implements Serializable {
432
409
  // kids[i] = new XMLElement(this, kid);
433
410
  // }
434
411
  // return kids;
435
- checkChildren();
436
- return children;
437
- }
438
-
439
-
440
- /**
441
- * Quick accessor for an element at a particular index.
442
- *
443
- * @webref xml:method
444
- * @brief Returns the child element with the specified index value or path
445
- */
446
- public XML getChild(int index) {
447
- checkChildren();
448
- return children[index];
449
- }
450
-
451
-
452
- /**
453
- * Get a child by its name or path.
454
- *
455
- * @param name element name or path/to/element
456
- * @return the first matching element or null if no match
457
- */
458
- public XML getChild(String name) {
459
- if (name.length() > 0 && name.charAt(0) == '/') {
460
- throw new IllegalArgumentException("getChild() should not begin with a slash");
461
- }
462
- if (name.indexOf('/') != -1) {
463
- return getChildRecursive(PApplet.split(name, '/'), 0);
464
- }
465
- int childCount = getChildCount();
466
- for (int i = 0; i < childCount; i++) {
467
- XML kid = getChild(i);
468
- String kidName = kid.getName();
469
- if (kidName != null && kidName.equals(name)) {
470
- return kid;
471
- }
472
- }
473
- return null;
474
- }
475
-
476
-
477
- /**
478
- * Internal helper function for getChild(String).
479
- *
480
- * @param items result of splitting the query on slashes
481
- * @param offset where in the items[] array we're currently looking
482
- * @return matching element or null if no match
483
- * @author processing.org
484
- */
485
- protected XML getChildRecursive(String[] items, int offset) {
486
- // if it's a number, do an index instead
487
- if (Character.isDigit(items[offset].charAt(0))) {
488
- XML kid = getChild(Integer.parseInt(items[offset]));
489
- if (offset == items.length-1) {
490
- return kid;
491
- } else {
492
- return kid.getChildRecursive(items, offset+1);
493
- }
494
- }
495
- int childCount = getChildCount();
496
- for (int i = 0; i < childCount; i++) {
497
- XML kid = getChild(i);
498
- String kidName = kid.getName();
499
- if (kidName != null && kidName.equals(items[offset])) {
500
- if (offset == items.length-1) {
501
- return kid;
502
- } else {
503
- return kid.getChildRecursive(items, offset+1);
412
+ checkChildren();
413
+ return children;
414
+ }
415
+
416
+ /**
417
+ * Quick accessor for an element at a particular index.
418
+ *
419
+ * @webref xml:method
420
+ * @brief Returns the child element with the specified index value or path
421
+ */
422
+ public XML getChild(int index) {
423
+ checkChildren();
424
+ return children[index];
425
+ }
426
+
427
+ /**
428
+ * Get a child by its name or path.
429
+ *
430
+ * @param name element name or path/to/element
431
+ * @return the first matching element or null if no match
432
+ */
433
+ public XML getChild(String name) {
434
+ if (name.length() > 0 && name.charAt(0) == '/') {
435
+ throw new IllegalArgumentException("getChild() should not begin with a slash");
436
+ }
437
+ if (name.indexOf('/') != -1) {
438
+ return getChildRecursive(PApplet.split(name, '/'), 0);
439
+ }
440
+ int childCount = getChildCount();
441
+ for (int i = 0; i < childCount; i++) {
442
+ XML kid = getChild(i);
443
+ String kidName = kid.getName();
444
+ if (kidName != null && kidName.equals(name)) {
445
+ return kid;
446
+ }
447
+ }
448
+ return null;
449
+ }
450
+
451
+ /**
452
+ * Internal helper function for getChild(String).
453
+ *
454
+ * @param items result of splitting the query on slashes
455
+ * @param offset where in the items[] array we're currently looking
456
+ * @return matching element or null if no match
457
+ * @author processing.org
458
+ */
459
+ protected XML getChildRecursive(String[] items, int offset) {
460
+ // if it's a number, do an index instead
461
+ if (Character.isDigit(items[offset].charAt(0))) {
462
+ XML kid = getChild(Integer.parseInt(items[offset]));
463
+ if (offset == items.length - 1) {
464
+ return kid;
465
+ } else {
466
+ return kid.getChildRecursive(items, offset + 1);
467
+ }
468
+ }
469
+ int childCount = getChildCount();
470
+ for (int i = 0; i < childCount; i++) {
471
+ XML kid = getChild(i);
472
+ String kidName = kid.getName();
473
+ if (kidName != null && kidName.equals(items[offset])) {
474
+ if (offset == items.length - 1) {
475
+ return kid;
476
+ } else {
477
+ return kid.getChildRecursive(items, offset + 1);
478
+ }
479
+ }
480
+ }
481
+ return null;
482
+ }
483
+
484
+ /**
485
+ * Get any children that match this name or path. Similar to getChild(), but
486
+ * will grab multiple matches rather than only the first.
487
+ *
488
+ * @param name element name or path/to/element
489
+ * @return array of child elements that match
490
+ * @author processing.org
491
+ */
492
+ public XML[] getChildren(String name) {
493
+ if (name.length() > 0 && name.charAt(0) == '/') {
494
+ throw new IllegalArgumentException("getChildren() should not begin with a slash");
495
+ }
496
+ if (name.indexOf('/') != -1) {
497
+ return getChildrenRecursive(PApplet.split(name, '/'), 0);
498
+ }
499
+ // if it's a number, do an index instead
500
+ // (returns a single element array, since this will be a single match
501
+ if (Character.isDigit(name.charAt(0))) {
502
+ return new XML[]{getChild(Integer.parseInt(name))};
503
+ }
504
+ int childCount = getChildCount();
505
+ XML[] matches = new XML[childCount];
506
+ int matchCount = 0;
507
+ for (int i = 0; i < childCount; i++) {
508
+ XML kid = getChild(i);
509
+ String kidName = kid.getName();
510
+ if (kidName != null && kidName.equals(name)) {
511
+ matches[matchCount++] = kid;
512
+ }
513
+ }
514
+ return (XML[]) PApplet.subset(matches, 0, matchCount);
515
+ }
516
+
517
+ protected XML[] getChildrenRecursive(String[] items, int offset) {
518
+ if (offset == items.length - 1) {
519
+ return getChildren(items[offset]);
520
+ }
521
+ XML[] matches = getChildren(items[offset]);
522
+ XML[] outgoing = new XML[0];
523
+ for (int i = 0; i < matches.length; i++) {
524
+ XML[] kidMatches = matches[i].getChildrenRecursive(items, offset + 1);
525
+ outgoing = (XML[]) PApplet.concat(outgoing, kidMatches);
526
+ }
527
+ return outgoing;
528
+ }
529
+
530
+ /**
531
+ * @webref xml:method
532
+ * @brief Appends a new child to the element
533
+ */
534
+ public XML addChild(String tag) {
535
+ Document document = node.getOwnerDocument();
536
+ Node newChild = document.createElement(tag);
537
+ return appendChild(newChild);
538
+ }
539
+
540
+ public XML addChild(XML child) {
541
+ Document document = node.getOwnerDocument();
542
+ Node newChild = document.importNode((Node) child.getNative(), true);
543
+ return appendChild(newChild);
544
+ }
545
+
546
+ /**
547
+ * Internal handler to add the node structure.
548
+ */
549
+ protected XML appendChild(Node newNode) {
550
+ node.appendChild(newNode);
551
+ XML newbie = new XML(this, newNode);
552
+ if (children != null) {
553
+ children = (XML[]) PApplet.concat(children, new XML[]{newbie});
504
554
  }
505
- }
506
- }
507
- return null;
508
- }
509
-
510
-
511
- /**
512
- * Get any children that match this name or path. Similar to getChild(),
513
- * but will grab multiple matches rather than only the first.
514
- *
515
- * @param name element name or path/to/element
516
- * @return array of child elements that match
517
- * @author processing.org
518
- */
519
- public XML[] getChildren(String name) {
520
- if (name.length() > 0 && name.charAt(0) == '/') {
521
- throw new IllegalArgumentException("getChildren() should not begin with a slash");
522
- }
523
- if (name.indexOf('/') != -1) {
524
- return getChildrenRecursive(PApplet.split(name, '/'), 0);
525
- }
526
- // if it's a number, do an index instead
527
- // (returns a single element array, since this will be a single match
528
- if (Character.isDigit(name.charAt(0))) {
529
- return new XML[] { getChild(Integer.parseInt(name)) };
530
- }
531
- int childCount = getChildCount();
532
- XML[] matches = new XML[childCount];
533
- int matchCount = 0;
534
- for (int i = 0; i < childCount; i++) {
535
- XML kid = getChild(i);
536
- String kidName = kid.getName();
537
- if (kidName != null && kidName.equals(name)) {
538
- matches[matchCount++] = kid;
539
- }
540
- }
541
- return (XML[]) PApplet.subset(matches, 0, matchCount);
542
- }
543
-
544
-
545
- protected XML[] getChildrenRecursive(String[] items, int offset) {
546
- if (offset == items.length-1) {
547
- return getChildren(items[offset]);
548
- }
549
- XML[] matches = getChildren(items[offset]);
550
- XML[] outgoing = new XML[0];
551
- for (int i = 0; i < matches.length; i++) {
552
- XML[] kidMatches = matches[i].getChildrenRecursive(items, offset+1);
553
- outgoing = (XML[]) PApplet.concat(outgoing, kidMatches);
554
- }
555
- return outgoing;
556
- }
557
-
558
-
559
- /**
560
- * @webref xml:method
561
- * @brief Appends a new child to the element
562
- */
563
- public XML addChild(String tag) {
564
- Document document = node.getOwnerDocument();
565
- Node newChild = document.createElement(tag);
566
- return appendChild(newChild);
567
- }
568
-
569
-
570
- public XML addChild(XML child) {
571
- Document document = node.getOwnerDocument();
572
- Node newChild = document.importNode((Node) child.getNative(), true);
573
- return appendChild(newChild);
574
- }
575
-
576
-
577
- /** Internal handler to add the node structure. */
578
- protected XML appendChild(Node newNode) {
579
- node.appendChild(newNode);
580
- XML newbie = new XML(this, newNode);
581
- if (children != null) {
582
- children = (XML[]) PApplet.concat(children, new XML[] { newbie });
583
- }
584
- return newbie;
585
- }
586
-
587
-
588
- /**
589
- * @webref xml:method
590
- * @brief Removes the specified child
591
- */
592
- public void removeChild(XML kid) {
593
- node.removeChild(kid.node);
594
- children = null; // TODO not efficient
595
- }
596
-
597
- /**
598
- * Removes whitespace nodes.
599
- * Those whitespace nodes are required to reconstruct the original XML's spacing and indentation.
600
- * If you call this and use saveXML() your original spacing will be gone.
601
- *
602
- * @nowebref
603
- * @brief Removes whitespace nodes
604
- */
605
- public void trim() {
606
- try {
607
- XPathFactory xpathFactory = XPathFactory.newInstance();
608
- XPathExpression xpathExp =
609
- xpathFactory.newXPath().compile("//text()[normalize-space(.) = '']");
610
- NodeList emptyTextNodes = (NodeList)
611
- xpathExp.evaluate(node, XPathConstants.NODESET);
612
-
613
- // Remove each empty text node from document.
614
- for (int i = 0; i < emptyTextNodes.getLength(); i++) {
615
- Node emptyTextNode = emptyTextNodes.item(i);
616
- emptyTextNode.getParentNode().removeChild(emptyTextNode);
617
- }
618
- } catch (Exception e) {
619
- throw new RuntimeException(e);
620
- }
621
- }
555
+ return newbie;
556
+ }
622
557
 
558
+ /**
559
+ * @webref xml:method
560
+ * @brief Removes the specified child
561
+ */
562
+ public void removeChild(XML kid) {
563
+ node.removeChild(kid.node);
564
+ children = null; // TODO not efficient
565
+ }
566
+
567
+ /**
568
+ * Removes whitespace nodes. Those whitespace nodes are required to
569
+ * reconstruct the original XML's spacing and indentation. If you call this
570
+ * and use saveXML() your original spacing will be gone.
571
+ *
572
+ * @nowebref
573
+ * @brief Removes whitespace nodes
574
+ */
575
+ public void trim() {
576
+ try {
577
+ XPathFactory xpathFactory = XPathFactory.newInstance();
578
+ XPathExpression xpathExp
579
+ = xpathFactory.newXPath().compile("//text()[normalize-space(.) = '']");
580
+ NodeList emptyTextNodes = (NodeList) xpathExp.evaluate(node, XPathConstants.NODESET);
581
+
582
+ // Remove each empty text node from document.
583
+ for (int i = 0; i < emptyTextNodes.getLength(); i++) {
584
+ Node emptyTextNode = emptyTextNodes.item(i);
585
+ emptyTextNode.getParentNode().removeChild(emptyTextNode);
586
+ }
587
+ } catch (Exception e) {
588
+ throw new RuntimeException(e);
589
+ }
590
+ }
623
591
 
624
592
  // /** Remove whitespace nodes. */
625
593
  // public void trim() {
@@ -668,489 +636,447 @@ public class XML implements Serializable {
668
636
  //// </xsl:template>
669
637
  //// </xsl:stylesheet>
670
638
  // }
639
+ /**
640
+ * Returns the number of attributes.
641
+ *
642
+ * @webref xml:method
643
+ * @brief Counts the specified element's number of attributes
644
+ */
645
+ public int getAttributeCount() {
646
+ return node.getAttributes().getLength();
647
+ }
648
+
649
+ /**
650
+ * Get a list of the names for all of the attributes for this node.
651
+ *
652
+ * @webref xml:method
653
+ * @brief Returns a list of names of all attributes as an array
654
+ */
655
+ public String[] listAttributes() {
656
+ NamedNodeMap nnm = node.getAttributes();
657
+ String[] outgoing = new String[nnm.getLength()];
658
+ for (int i = 0; i < outgoing.length; i++) {
659
+ outgoing[i] = nnm.item(i).getNodeName();
660
+ }
661
+ return outgoing;
662
+ }
671
663
 
664
+ /**
665
+ * Returns whether an attribute exists.
666
+ *
667
+ * @webref xml:method
668
+ * @brief Checks whether or not an element has the specified attribute
669
+ */
670
+ public boolean hasAttribute(String name) {
671
+ return (node.getAttributes().getNamedItem(name) != null);
672
+ }
672
673
 
673
- /**
674
- * Returns the number of attributes.
675
- *
676
- * @webref xml:method
677
- * @brief Counts the specified element's number of attributes
678
- */
679
- public int getAttributeCount() {
680
- return node.getAttributes().getLength();
681
- }
682
-
683
-
684
- /**
685
- * Get a list of the names for all of the attributes for this node.
686
- *
687
- * @webref xml:method
688
- * @brief Returns a list of names of all attributes as an array
689
- */
690
- public String[] listAttributes() {
691
- NamedNodeMap nnm = node.getAttributes();
692
- String[] outgoing = new String[nnm.getLength()];
693
- for (int i = 0; i < outgoing.length; i++) {
694
- outgoing[i] = nnm.item(i).getNodeName();
695
- }
696
- return outgoing;
697
- }
698
-
699
- /**
700
- * Returns whether an attribute exists.
701
- *
702
- * @webref xml:method
703
- * @brief Checks whether or not an element has the specified attribute
704
- */
705
- public boolean hasAttribute(String name) {
706
- return (node.getAttributes().getNamedItem(name) != null);
707
- }
708
-
709
-
710
- /**
711
- * Returns the value of an attribute.
712
- *
713
- * @param name the non-null name of the attribute.
714
- * @return the value, or null if the attribute does not exist.
715
- */
674
+ /**
675
+ * Returns the value of an attribute.
676
+ *
677
+ * @param name the non-null name of the attribute.
678
+ * @return the value, or null if the attribute does not exist.
679
+ */
716
680
  // public String getAttribute(String name) {
717
681
  // return this.getAttribute(name, null);
718
682
  // }
719
-
720
-
721
- /**
722
- * Returns the value of an attribute.
723
- *
724
- * @param name the non-null full name of the attribute.
725
- * @param defaultValue the default value of the attribute.
726
- * @return the value, or defaultValue if the attribute does not exist.
727
- */
683
+ /**
684
+ * Returns the value of an attribute.
685
+ *
686
+ * @param name the non-null full name of the attribute.
687
+ * @param defaultValue the default value of the attribute.
688
+ * @return the value, or defaultValue if the attribute does not exist.
689
+ */
728
690
  // public String getAttribute(String name, String defaultValue) {
729
691
  // Node attr = node.getAttributes().getNamedItem(name);
730
692
  // return (attr == null) ? defaultValue : attr.getNodeValue();
731
693
  // }
694
+ /**
695
+ * @webref xml:method
696
+ * @brief Gets the content of an attribute as a String
697
+ */
698
+ public String getString(String name) {
699
+ return getString(name, null);
700
+ }
701
+
702
+ public String getString(String name, String defaultValue) {
703
+ NamedNodeMap attrs = node.getAttributes();
704
+ if (attrs != null) {
705
+ Node attr = attrs.getNamedItem(name);
706
+ if (attr != null) {
707
+ return attr.getNodeValue();
708
+ }
709
+ }
710
+ return defaultValue;
711
+ }
732
712
 
713
+ /**
714
+ * @webref xml:method
715
+ * @brief Sets the content of an attribute as a String
716
+ */
717
+ public void setString(String name, String value) {
718
+ ((Element) node).setAttribute(name, value);
719
+ }
733
720
 
734
- /**
735
- * @webref xml:method
736
- * @brief Gets the content of an attribute as a String
737
- */
738
- public String getString(String name) {
739
- return getString(name, null);
740
- }
741
-
742
-
743
- public String getString(String name, String defaultValue) {
744
- NamedNodeMap attrs = node.getAttributes();
745
- if (attrs != null) {
746
- Node attr = attrs.getNamedItem(name);
747
- if (attr != null) {
748
- return attr.getNodeValue();
749
- }
750
- }
751
- return defaultValue;
752
- }
753
-
754
-
755
- /**
756
- * @webref xml:method
757
- * @brief Sets the content of an attribute as a String
758
- */
759
- public void setString(String name, String value) {
760
- ((Element) node).setAttribute(name, value);
761
- }
762
-
763
-
764
- /**
765
- * @webref xml:method
766
- * @brief Gets the content of an attribute as an int
767
- */
768
- public int getInt(String name) {
769
- return getInt(name, 0);
770
- }
771
-
772
-
773
- /**
774
- * @webref xml:method
775
- * @brief Sets the content of an attribute as an int
776
- */
777
- public void setInt(String name, int value) {
778
- setString(name, String.valueOf(value));
779
- }
780
-
781
-
782
- /**
783
- * Returns the value of an attribute.
784
- *
785
- * @param name the non-null full name of the attribute
786
- * @param defaultValue the default value of the attribute
787
- * @return the value, or defaultValue if the attribute does not exist
788
- */
789
- public int getInt(String name, int defaultValue) {
790
- String value = getString(name);
791
- return (value == null) ? defaultValue : Integer.parseInt(value);
792
- }
793
-
794
-
795
- /**
796
- * @webref xml:method
797
- * @brief Sets the content of an element as an int
798
- */
799
- public void setLong(String name, long value) {
800
- setString(name, String.valueOf(value));
801
- }
802
-
803
-
804
- /**
805
- * Returns the value of an attribute.
806
- *
807
- * @param name the non-null full name of the attribute.
808
- * @param defaultValue the default value of the attribute.
809
- * @return the value, or defaultValue if the attribute does not exist.
810
- */
811
- public long getLong(String name, long defaultValue) {
812
- String value = getString(name);
813
- return (value == null) ? defaultValue : Long.parseLong(value);
814
- }
815
-
816
-
817
- /**
818
- * Returns the value of an attribute, or zero if not present.
819
- *
820
- * @webref xml:method
821
- * @brief Gets the content of an attribute as a float
822
- */
823
- public float getFloat(String name) {
824
- return getFloat(name, 0);
825
- }
826
-
827
-
828
- /**
829
- * Returns the value of an attribute.
830
- *
831
- * @param name the non-null full name of the attribute.
832
- * @param defaultValue the default value of the attribute.
833
- * @return the value, or defaultValue if the attribute does not exist.
834
- */
835
- public float getFloat(String name, float defaultValue) {
836
- String value = getString(name);
837
- return (value == null) ? defaultValue : Float.parseFloat(value);
838
- }
839
-
840
-
841
- /**
842
- * @webref xml:method
843
- * @brief Sets the content of an attribute as a float
844
- */
845
- public void setFloat(String name, float value) {
846
- setString(name, String.valueOf(value));
847
- }
848
-
849
-
850
- public double getDouble(String name) {
851
- return getDouble(name, 0);
852
- }
853
-
854
-
855
- /**
856
- * Returns the value of an attribute.
857
- *
858
- * @param name the non-null full name of the attribute
859
- * @param defaultValue the default value of the attribute
860
- * @return the value, or defaultValue if the attribute does not exist
861
- */
862
- public double getDouble(String name, double defaultValue) {
863
- String value = getString(name);
864
- return (value == null) ? defaultValue : Double.parseDouble(value);
865
- }
866
-
867
-
868
- public void setDouble(String name, double value) {
869
- setString(name, String.valueOf(value));
870
- }
871
-
872
-
873
- /**
874
- * Return the #PCDATA content of the element. If the element has a
875
- * combination of #PCDATA content and child elements, the #PCDATA
876
- * sections can be retrieved as unnamed child objects. In this case,
877
- * this method returns null.
878
- *
879
- * @webref xml:method
880
- * @brief Gets the content of an element
881
- * @return the content.
882
- * @see XML#getIntContent()
883
- * @see XML#getFloatContent()
884
- */
885
- public String getContent() {
886
- return node.getTextContent();
887
- }
888
-
889
-
890
- public String getContent(String defaultValue) {
891
- String s = node.getTextContent();
892
- return (s != null) ? s : defaultValue;
893
- }
894
-
895
-
896
- /**
897
- * @webref xml:method
898
- * @brief Gets the content of an element as an int
899
- * @return the content.
900
- * @see XML#getContent()
901
- * @see XML#getFloatContent()
902
- */
903
- public int getIntContent() {
904
- return getIntContent(0);
905
- }
906
-
907
-
908
- /**
909
- * @param defaultValue the default value of the attribute
910
- */
911
- public int getIntContent(int defaultValue) {
912
- return PApplet.parseInt(node.getTextContent(), defaultValue);
913
- }
914
-
915
-
916
- /**
917
- * @webref xml:method
918
- * @brief Gets the content of an element as a float
919
- * @return the content.
920
- * @see XML#getContent()
921
- * @see XML#getIntContent()
922
- */
923
- public float getFloatContent() {
924
- return getFloatContent(0);
925
- }
926
-
927
-
928
- /**
929
- * @param defaultValue the default value of the attribute
930
- */
931
- public float getFloatContent(float defaultValue) {
932
- return PApplet.parseFloat(node.getTextContent(), defaultValue);
933
- }
934
-
935
-
936
- public long getLongContent() {
937
- return getLongContent(0);
938
- }
939
-
940
-
941
- public long getLongContent(long defaultValue) {
942
- String c = node.getTextContent();
943
- if (c != null) {
944
- try {
945
- return Long.parseLong(c);
946
- } catch (NumberFormatException nfe) { }
947
- }
948
- return defaultValue;
949
- }
950
-
951
-
952
- public double getDoubleContent() {
953
- return getDoubleContent(0);
954
- }
955
-
956
-
957
- public double getDoubleContent(double defaultValue) {
958
- String c = node.getTextContent();
959
- if (c != null) {
960
- try {
961
- return Double.parseDouble(c);
962
- } catch (NumberFormatException nfe) { }
963
- }
964
- return defaultValue;
965
- }
966
-
967
-
968
- /**
969
- * @webref xml:method
970
- * @brief Sets the content of an element
971
- */
972
- public void setContent(String text) {
973
- node.setTextContent(text);
974
- }
975
-
976
-
977
- public void setIntContent(int value) {
978
- setContent(String.valueOf(value));
979
- }
721
+ /**
722
+ * @webref xml:method
723
+ * @brief Gets the content of an attribute as an int
724
+ */
725
+ public int getInt(String name) {
726
+ return getInt(name, 0);
727
+ }
980
728
 
729
+ /**
730
+ * @webref xml:method
731
+ * @brief Sets the content of an attribute as an int
732
+ */
733
+ public void setInt(String name, int value) {
734
+ setString(name, String.valueOf(value));
735
+ }
981
736
 
982
- public void setFloatContent(float value) {
983
- setContent(String.valueOf(value));
984
- }
737
+ /**
738
+ * Returns the value of an attribute.
739
+ *
740
+ * @param name the non-null full name of the attribute
741
+ * @param defaultValue the default value of the attribute
742
+ * @return the value, or defaultValue if the attribute does not exist
743
+ */
744
+ public int getInt(String name, int defaultValue) {
745
+ String value = getString(name);
746
+ return (value == null) ? defaultValue : Integer.parseInt(value);
747
+ }
985
748
 
749
+ /**
750
+ * @webref xml:method
751
+ * @brief Sets the content of an element as an int
752
+ */
753
+ public void setLong(String name, long value) {
754
+ setString(name, String.valueOf(value));
755
+ }
986
756
 
987
- public void setLongContent(long value) {
988
- setContent(String.valueOf(value));
989
- }
757
+ /**
758
+ * Returns the value of an attribute.
759
+ *
760
+ * @param name the non-null full name of the attribute.
761
+ * @param defaultValue the default value of the attribute.
762
+ * @return the value, or defaultValue if the attribute does not exist.
763
+ */
764
+ public long getLong(String name, long defaultValue) {
765
+ String value = getString(name);
766
+ return (value == null) ? defaultValue : Long.parseLong(value);
767
+ }
990
768
 
769
+ /**
770
+ * Returns the value of an attribute, or zero if not present.
771
+ *
772
+ * @webref xml:method
773
+ * @brief Gets the content of an attribute as a float
774
+ */
775
+ public float getFloat(String name) {
776
+ return getFloat(name, 0);
777
+ }
991
778
 
992
- public void setDoubleContent(double value) {
993
- setContent(String.valueOf(value));
994
- }
779
+ /**
780
+ * Returns the value of an attribute.
781
+ *
782
+ * @param name the non-null full name of the attribute.
783
+ * @param defaultValue the default value of the attribute.
784
+ * @return the value, or defaultValue if the attribute does not exist.
785
+ */
786
+ public float getFloat(String name, float defaultValue) {
787
+ String value = getString(name);
788
+ return (value == null) ? defaultValue : Float.parseFloat(value);
789
+ }
995
790
 
996
-
997
- /**
998
- * Format this XML data as a String.
999
- *
1000
- * @webref xml:method
1001
- * @brief Formats XML data as a String
1002
- * @param indent -1 for a single line (and no declaration), >= 0 for indents and newlines
1003
- * @return the content
1004
- * @see XML#toString()
1005
- */
1006
- public String format(int indent) {
1007
- try {
1008
- // entities = doctype.getEntities()
1009
- boolean useIndentAmount = false;
1010
- TransformerFactory factory = TransformerFactory.newInstance();
1011
- if (indent != -1) {
1012
- try {
1013
- factory.setAttribute("indent-number", indent);
1014
- } catch (IllegalArgumentException e) {
1015
- useIndentAmount = true;
791
+ /**
792
+ * @webref xml:method
793
+ * @brief Sets the content of an attribute as a float
794
+ */
795
+ public void setFloat(String name, float value) {
796
+ setString(name, String.valueOf(value));
797
+ }
798
+
799
+ public double getDouble(String name) {
800
+ return getDouble(name, 0);
801
+ }
802
+
803
+ /**
804
+ * Returns the value of an attribute.
805
+ *
806
+ * @param name the non-null full name of the attribute
807
+ * @param defaultValue the default value of the attribute
808
+ * @return the value, or defaultValue if the attribute does not exist
809
+ */
810
+ public double getDouble(String name, double defaultValue) {
811
+ String value = getString(name);
812
+ return (value == null) ? defaultValue : Double.parseDouble(value);
813
+ }
814
+
815
+ public void setDouble(String name, double value) {
816
+ setString(name, String.valueOf(value));
817
+ }
818
+
819
+ /**
820
+ * Return the #PCDATA content of the element. If the element has a
821
+ * combination of #PCDATA content and child elements, the #PCDATA sections
822
+ * can be retrieved as unnamed child objects. In this case, this method
823
+ * returns null.
824
+ *
825
+ * @webref xml:method
826
+ * @brief Gets the content of an element
827
+ * @return the content.
828
+ * @see XML#getIntContent()
829
+ * @see XML#getFloatContent()
830
+ */
831
+ public String getContent() {
832
+ return node.getTextContent();
833
+ }
834
+
835
+ public String getContent(String defaultValue) {
836
+ String s = node.getTextContent();
837
+ return (s != null) ? s : defaultValue;
838
+ }
839
+
840
+ /**
841
+ * @webref xml:method
842
+ * @brief Gets the content of an element as an int
843
+ * @return the content.
844
+ * @see XML#getContent()
845
+ * @see XML#getFloatContent()
846
+ */
847
+ public int getIntContent() {
848
+ return getIntContent(0);
849
+ }
850
+
851
+ /**
852
+ * @param defaultValue the default value of the attribute
853
+ */
854
+ public int getIntContent(int defaultValue) {
855
+ return PApplet.parseInt(node.getTextContent(), defaultValue);
856
+ }
857
+
858
+ /**
859
+ * @webref xml:method
860
+ * @brief Gets the content of an element as a float
861
+ * @return the content.
862
+ * @see XML#getContent()
863
+ * @see XML#getIntContent()
864
+ */
865
+ public float getFloatContent() {
866
+ return getFloatContent(0);
867
+ }
868
+
869
+ /**
870
+ * @param defaultValue the default value of the attribute
871
+ */
872
+ public float getFloatContent(float defaultValue) {
873
+ return PApplet.parseFloat(node.getTextContent(), defaultValue);
874
+ }
875
+
876
+ public long getLongContent() {
877
+ return getLongContent(0);
878
+ }
879
+
880
+ public long getLongContent(long defaultValue) {
881
+ String c = node.getTextContent();
882
+ if (c != null) {
883
+ try {
884
+ return Long.parseLong(c);
885
+ } catch (NumberFormatException nfe) {
886
+ }
1016
887
  }
1017
- }
1018
- Transformer transformer = factory.newTransformer();
888
+ return defaultValue;
889
+ }
1019
890
 
1020
- // Add the XML declaration at the top if this node is the root and we're
1021
- // not writing to a single line (indent = -1 means single line).
1022
- if (indent == -1 || parent == null) {
1023
- transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
1024
- } else {
1025
- transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
1026
- }
891
+ public double getDoubleContent() {
892
+ return getDoubleContent(0);
893
+ }
1027
894
 
1028
- // transformer.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM, "sample.dtd");
895
+ public double getDoubleContent(double defaultValue) {
896
+ String c = node.getTextContent();
897
+ if (c != null) {
898
+ try {
899
+ return Double.parseDouble(c);
900
+ } catch (NumberFormatException nfe) {
901
+ }
902
+ }
903
+ return defaultValue;
904
+ }
1029
905
 
1030
- transformer.setOutputProperty(OutputKeys.METHOD, "xml");
906
+ /**
907
+ * @webref xml:method
908
+ * @brief Sets the content of an element
909
+ */
910
+ public void setContent(String text) {
911
+ node.setTextContent(text);
912
+ }
1031
913
 
1032
- // transformer.setOutputProperty(OutputKeys.CDATA_SECTION_ELEMENTS, "yes"); // huh?
914
+ public void setIntContent(int value) {
915
+ setContent(String.valueOf(value));
916
+ }
1033
917
 
918
+ public void setFloatContent(float value) {
919
+ setContent(String.valueOf(value));
920
+ }
921
+
922
+ public void setLongContent(long value) {
923
+ setContent(String.valueOf(value));
924
+ }
925
+
926
+ public void setDoubleContent(double value) {
927
+ setContent(String.valueOf(value));
928
+ }
929
+
930
+ /**
931
+ * Format this XML data as a String.
932
+ *
933
+ * @webref xml:method
934
+ * @brief Formats XML data as a String
935
+ * @param indent -1 for a single line (and no declaration), >= 0 for indents
936
+ * and newlines
937
+ * @return the content
938
+ * @see XML#toString()
939
+ */
940
+ public String format(int indent) {
941
+ try {
942
+ // entities = doctype.getEntities()
943
+ boolean useIndentAmount = false;
944
+ TransformerFactory factory = TransformerFactory.newInstance();
945
+ if (indent != -1) {
946
+ try {
947
+ factory.setAttribute("indent-number", indent);
948
+ } catch (IllegalArgumentException e) {
949
+ useIndentAmount = true;
950
+ }
951
+ }
952
+ Transformer transformer = factory.newTransformer();
953
+
954
+ // Add the XML declaration at the top if this node is the root and we're
955
+ // not writing to a single line (indent = -1 means single line).
956
+ if (indent == -1 || parent == null) {
957
+ transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
958
+ } else {
959
+ transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
960
+ }
961
+
962
+ // transformer.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM, "sample.dtd");
963
+ transformer.setOutputProperty(OutputKeys.METHOD, "xml");
964
+
965
+ // transformer.setOutputProperty(OutputKeys.CDATA_SECTION_ELEMENTS, "yes"); // huh?
1034
966
  // transformer.setOutputProperty(OutputKeys.DOCTYPE_PUBLIC,
1035
967
  // "-//W3C//DTD XHTML 1.0 Transitional//EN");
1036
968
  // transformer.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM,
1037
969
  // "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd");
1038
-
1039
- // For Android, because (at least 2.3.3) doesn't like indent-number
1040
- if (useIndentAmount) {
1041
- transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", String.valueOf(indent));
1042
- }
970
+ // For Android, because (at least 2.3.3) doesn't like indent-number
971
+ if (useIndentAmount) {
972
+ transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", String.valueOf(indent));
973
+ }
1043
974
 
1044
975
  // transformer.setOutputProperty(OutputKeys.ENCODING,"ISO-8859-1");
1045
976
  // transformer.setOutputProperty(OutputKeys.ENCODING,"UTF8");
1046
- transformer.setOutputProperty(OutputKeys.ENCODING,"UTF-8");
977
+ transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
1047
978
  // transformer.setOutputProperty(OutputKeys.CDATA_SECTION_ELEMENTS
1048
979
 
1049
- // Always indent, otherwise the XML declaration will just be jammed
1050
- // onto the first line with the XML code as well.
1051
- transformer.setOutputProperty(OutputKeys.INDENT, "yes");
980
+ // Always indent, otherwise the XML declaration will just be jammed
981
+ // onto the first line with the XML code as well.
982
+ transformer.setOutputProperty(OutputKeys.INDENT, "yes");
1052
983
 
1053
984
  // Properties p = transformer.getOutputProperties();
1054
985
  // for (Object key : p.keySet()) {
1055
986
  // System.out.println(key + " -> " + p.get(key));
1056
987
  // }
1057
-
1058
- // If you smell something, that's because this code stinks. No matter
1059
- // the settings of the Transformer object, if the XML document already
1060
- // has whitespace elements, it won't bother re-indenting/re-formatting.
1061
- // So instead, transform the data once into a single line string.
1062
- // If indent is -1, then we're done. Otherwise re-run and the settings
1063
- // of the factory will kick in. If you know a better way to do this,
1064
- // please contribute. I've wasted too much of my Sunday on it. But at
1065
- // least the Giants are getting blown out by the Falcons.
1066
-
1067
- final String decl = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
1068
- final String sep = System.getProperty("line.separator");
1069
-
1070
- StringWriter tempWriter = new StringWriter();
1071
- StreamResult tempResult = new StreamResult(tempWriter);
1072
- transformer.transform(new DOMSource(node), tempResult);
1073
- String[] tempLines = PApplet.split(tempWriter.toString(), sep);
988
+ // If you smell something, that's because this code stinks. No matter
989
+ // the settings of the Transformer object, if the XML document already
990
+ // has whitespace elements, it won't bother re-indenting/re-formatting.
991
+ // So instead, transform the data once into a single line string.
992
+ // If indent is -1, then we're done. Otherwise re-run and the settings
993
+ // of the factory will kick in. If you know a better way to do this,
994
+ // please contribute. I've wasted too much of my Sunday on it. But at
995
+ // least the Giants are getting blown out by the Falcons.
996
+ final String decl = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
997
+ final String sep = System.getProperty("line.separator");
998
+
999
+ StringWriter tempWriter = new StringWriter();
1000
+ StreamResult tempResult = new StreamResult(tempWriter);
1001
+ transformer.transform(new DOMSource(node), tempResult);
1002
+ String[] tempLines = PApplet.split(tempWriter.toString(), sep);
1074
1003
  // PApplet.println(tempLines);
1075
- if (tempLines[0].startsWith("<?xml")) {
1076
- // Remove XML declaration from the top before slamming into one line
1077
- int declEnd = tempLines[0].indexOf("?>") + 2;
1078
- //if (tempLines[0].length() == decl.length()) {
1079
- if (tempLines[0].length() == declEnd) {
1080
- // If it's all the XML declaration, remove it
1004
+ if (tempLines[0].startsWith("<?xml")) {
1005
+ // Remove XML declaration from the top before slamming into one line
1006
+ int declEnd = tempLines[0].indexOf("?>") + 2;
1007
+ //if (tempLines[0].length() == decl.length()) {
1008
+ if (tempLines[0].length() == declEnd) {
1009
+ // If it's all the XML declaration, remove it
1081
1010
  // PApplet.println("removing first line");
1082
- tempLines = PApplet.subset(tempLines, 1);
1083
- } else {
1011
+ tempLines = PApplet.subset(tempLines, 1);
1012
+ } else {
1084
1013
  // PApplet.println("removing part of first line");
1085
- // If the first node has been moved to this line, be more careful
1086
- //tempLines[0] = tempLines[0].substring(decl.length());
1087
- tempLines[0] = tempLines[0].substring(declEnd);
1088
- }
1089
- }
1090
- String singleLine = PApplet.join(PApplet.trim(tempLines), "");
1091
- if (indent == -1) {
1092
- return singleLine;
1093
- }
1094
-
1095
- // Might just be whitespace, which won't be valid XML for parsing below.
1096
- // https://github.com/processing/processing/issues/1796
1097
- // Since indent is not -1, that means they want valid XML,
1098
- // so we'll give them the single line plus the decl... Lame? sure.
1099
- if (singleLine.trim().length() == 0) {
1100
- // You want whitespace? I've got your whitespace right here.
1101
- return decl + sep + singleLine;
1102
- }
1103
-
1104
- // Since the indent is not -1, bring back the XML declaration
1105
- //transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
1106
-
1107
- StringWriter stringWriter = new StringWriter();
1108
- StreamResult xmlOutput = new StreamResult(stringWriter);
1014
+ // If the first node has been moved to this line, be more careful
1015
+ //tempLines[0] = tempLines[0].substring(decl.length());
1016
+ tempLines[0] = tempLines[0].substring(declEnd);
1017
+ }
1018
+ }
1019
+ String singleLine = PApplet.join(PApplet.trim(tempLines), "");
1020
+ if (indent == -1) {
1021
+ return singleLine;
1022
+ }
1023
+
1024
+ // Might just be whitespace, which won't be valid XML for parsing below.
1025
+ // https://github.com/processing/processing/issues/1796
1026
+ // Since indent is not -1, that means they want valid XML,
1027
+ // so we'll give them the single line plus the decl... Lame? sure.
1028
+ if (singleLine.trim().length() == 0) {
1029
+ // You want whitespace? I've got your whitespace right here.
1030
+ return decl + sep + singleLine;
1031
+ }
1032
+
1033
+ // Since the indent is not -1, bring back the XML declaration
1034
+ //transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
1035
+ StringWriter stringWriter = new StringWriter();
1036
+ StreamResult xmlOutput = new StreamResult(stringWriter);
1109
1037
  // DOMSource source = new DOMSource(node);
1110
- Source source = new StreamSource(new StringReader(singleLine));
1111
- transformer.transform(source, xmlOutput);
1112
- String outgoing = stringWriter.toString();
1113
-
1114
- // Add the XML declaration to the top if it's not there already
1115
- if (outgoing.startsWith(decl)) {
1116
- int declen = decl.length();
1117
- int seplen = sep.length();
1118
- if (outgoing.length() > declen + seplen &&
1119
- !outgoing.substring(declen, declen + seplen).equals(sep)) {
1120
- // make sure there's a line break between the XML decl and the code
1121
- return outgoing.substring(0, decl.length()) +
1122
- sep + outgoing.substring(decl.length());
1038
+ Source source = new StreamSource(new StringReader(singleLine));
1039
+ transformer.transform(source, xmlOutput);
1040
+ String outgoing = stringWriter.toString();
1041
+
1042
+ // Add the XML declaration to the top if it's not there already
1043
+ if (outgoing.startsWith(decl)) {
1044
+ int declen = decl.length();
1045
+ int seplen = sep.length();
1046
+ if (outgoing.length() > declen + seplen
1047
+ && !outgoing.substring(declen, declen + seplen).equals(sep)) {
1048
+ // make sure there's a line break between the XML decl and the code
1049
+ return outgoing.substring(0, decl.length())
1050
+ + sep + outgoing.substring(decl.length());
1051
+ }
1052
+ return outgoing;
1053
+ } else {
1054
+ return decl + sep + outgoing;
1055
+ }
1056
+
1057
+ } catch (Exception e) {
1058
+ e.printStackTrace();
1123
1059
  }
1124
- return outgoing;
1125
- } else {
1126
- return decl + sep + outgoing;
1127
- }
1128
-
1129
- } catch (Exception e) {
1130
- e.printStackTrace();
1131
- }
1132
- return null;
1133
- }
1134
-
1135
-
1136
- public void print() {
1137
- PApplet.println(format(2));
1138
- }
1139
-
1140
-
1141
- /**
1142
- * Return the XML document formatted with two spaces for indents.
1143
- * Chosen to do this since it's the most common case (e.g. with println()).
1144
- * Same as format(2). Use the format() function for more options.
1145
- *
1146
- * @webref xml:method
1147
- * @brief Gets XML data as a String using default formatting
1148
- * @return the content
1149
- * @see XML#format(int)
1150
- */
1151
- @Override
1152
- public String toString() {
1153
- //return format(2);
1154
- return format(-1);
1155
- }
1060
+ return null;
1061
+ }
1062
+
1063
+ public void print() {
1064
+ PApplet.println(format(2));
1065
+ }
1066
+
1067
+ /**
1068
+ * Return the XML document formatted with two spaces for indents. Chosen to
1069
+ * do this since it's the most common case (e.g. with println()). Same as
1070
+ * format(2). Use the format() function for more options.
1071
+ *
1072
+ * @webref xml:method
1073
+ * @brief Gets XML data as a String using default formatting
1074
+ * @return the content
1075
+ * @see XML#format(int)
1076
+ */
1077
+ @Override
1078
+ public String toString() {
1079
+ //return format(2);
1080
+ return format(-1);
1081
+ }
1156
1082
  }