propane 3.4.2-java → 3.8.0-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (140) hide show
  1. checksums.yaml +4 -4
  2. data/.mvn/extensions.xml +1 -1
  3. data/.mvn/wrapper/MavenWrapperDownloader.java +2 -2
  4. data/.mvn/wrapper/maven-wrapper.properties +2 -2
  5. data/.travis.yml +1 -1
  6. data/CHANGELOG.md +9 -1
  7. data/Gemfile +2 -0
  8. data/README.md +7 -10
  9. data/Rakefile +10 -11
  10. data/bin/propane +3 -1
  11. data/lib/propane.rb +4 -2
  12. data/lib/propane/app.rb +5 -1
  13. data/lib/propane/creators/sketch_class.rb +7 -1
  14. data/lib/propane/creators/sketch_factory.rb +4 -2
  15. data/lib/propane/creators/sketch_writer.rb +1 -0
  16. data/lib/propane/helper_methods.rb +22 -23
  17. data/lib/propane/helpers/numeric.rb +2 -0
  18. data/lib/propane/helpers/version_error.rb +1 -0
  19. data/lib/propane/library.rb +5 -1
  20. data/lib/propane/library_loader.rb +2 -0
  21. data/lib/propane/native_folder.rb +10 -9
  22. data/lib/propane/native_loader.rb +3 -0
  23. data/lib/propane/runner.rb +20 -14
  24. data/lib/propane/version.rb +2 -1
  25. data/library/boids/boids.rb +21 -11
  26. data/library/color_group/color_group.rb +2 -0
  27. data/library/control_panel/control_panel.rb +8 -5
  28. data/library/dxf/dxf.rb +2 -0
  29. data/library/file_chooser/chooser.rb +10 -9
  30. data/library/file_chooser/file_chooser.rb +10 -9
  31. data/library/library_proxy/library_proxy.rb +2 -0
  32. data/library/net/net.rb +2 -0
  33. data/library/slider/slider.rb +23 -22
  34. data/library/vector_utils/vector_utils.rb +4 -0
  35. data/library/video_event/video_event.rb +2 -0
  36. data/pom.rb +37 -36
  37. data/pom.xml +7 -7
  38. data/propane.gemspec +13 -9
  39. data/src/main/java/japplemenubar/JAppleMenuBar.java +3 -3
  40. data/src/main/java/monkstone/ColorUtil.java +1 -3
  41. data/src/main/java/monkstone/MathToolModule.java +1 -1
  42. data/src/main/java/monkstone/PropaneLibrary.java +2 -2
  43. data/src/main/java/monkstone/fastmath/DegLutTables.java +111 -0
  44. data/src/main/java/monkstone/fastmath/Deglut.java +6 -56
  45. data/src/main/java/monkstone/filechooser/Chooser.java +1 -1
  46. data/src/main/java/monkstone/noise/Noise.java +116 -0
  47. data/src/main/java/monkstone/noise/NoiseGenerator.java +63 -0
  48. data/src/main/java/monkstone/noise/NoiseMode.java +15 -0
  49. data/src/main/java/monkstone/noise/SimplexNoise.java +137 -103
  50. data/src/main/java/monkstone/noise/ValueNoise.java +170 -0
  51. data/src/main/java/monkstone/slider/CustomHorizontalSlider.java +1 -1
  52. data/src/main/java/monkstone/slider/CustomVerticalSlider.java +1 -1
  53. data/src/main/java/monkstone/slider/SimpleHorizontalSlider.java +1 -1
  54. data/src/main/java/monkstone/slider/SimpleVerticalSlider.java +1 -1
  55. data/src/main/java/monkstone/slider/SliderBar.java +1 -1
  56. data/src/main/java/monkstone/slider/SliderGroup.java +1 -1
  57. data/src/main/java/monkstone/slider/WheelHandler.java +1 -1
  58. data/src/main/java/monkstone/vecmath/package-info.java +1 -1
  59. data/src/main/java/monkstone/vecmath/vec2/Vec2.java +1 -1
  60. data/src/main/java/monkstone/vecmath/vec3/Vec3.java +1 -2
  61. data/src/main/java/monkstone/videoevent/CaptureEvent.java +1 -1
  62. data/src/main/java/monkstone/videoevent/MovieEvent.java +1 -1
  63. data/src/main/java/monkstone/videoevent/package-info.java +1 -1
  64. data/src/main/java/processing/awt/PGraphicsJava2D.java +781 -285
  65. data/src/main/java/processing/awt/PImageAWT.java +377 -0
  66. data/src/main/java/processing/awt/PShapeJava2D.java +56 -52
  67. data/src/main/java/processing/awt/PSurfaceAWT.java +308 -208
  68. data/src/main/java/processing/awt/ShimAWT.java +581 -0
  69. data/src/main/java/processing/core/PApplet.java +13142 -13883
  70. data/src/main/java/processing/core/PConstants.java +477 -447
  71. data/src/main/java/processing/core/PFont.java +914 -880
  72. data/src/main/java/processing/core/PGraphics.java +152 -136
  73. data/src/main/java/processing/core/PImage.java +275 -372
  74. data/src/main/java/processing/core/PMatrix.java +172 -159
  75. data/src/main/java/processing/core/PMatrix2D.java +478 -415
  76. data/src/main/java/processing/core/PMatrix3D.java +762 -735
  77. data/src/main/java/processing/core/PShape.java +2887 -2651
  78. data/src/main/java/processing/core/PShapeOBJ.java +97 -92
  79. data/src/main/java/processing/core/PShapeSVG.java +1705 -1490
  80. data/src/main/java/processing/core/PStyle.java +40 -37
  81. data/src/main/java/processing/core/PSurface.java +139 -97
  82. data/src/main/java/processing/core/PSurfaceNone.java +296 -218
  83. data/src/main/java/processing/core/PVector.java +995 -963
  84. data/src/main/java/processing/core/ThinkDifferent.java +12 -8
  85. data/src/main/java/processing/data/DoubleDict.java +756 -710
  86. data/src/main/java/processing/data/DoubleList.java +749 -696
  87. data/src/main/java/processing/data/FloatDict.java +748 -702
  88. data/src/main/java/processing/data/FloatList.java +751 -697
  89. data/src/main/java/processing/data/IntDict.java +720 -673
  90. data/src/main/java/processing/data/IntList.java +699 -633
  91. data/src/main/java/processing/data/JSONArray.java +931 -873
  92. data/src/main/java/processing/data/JSONObject.java +1262 -1165
  93. data/src/main/java/processing/data/JSONTokener.java +351 -341
  94. data/src/main/java/processing/data/LongDict.java +710 -663
  95. data/src/main/java/processing/data/LongList.java +701 -635
  96. data/src/main/java/processing/data/Sort.java +37 -41
  97. data/src/main/java/processing/data/StringDict.java +525 -486
  98. data/src/main/java/processing/data/StringList.java +626 -580
  99. data/src/main/java/processing/data/Table.java +3690 -3510
  100. data/src/main/java/processing/data/TableRow.java +182 -183
  101. data/src/main/java/processing/data/XML.java +957 -883
  102. data/src/main/java/processing/event/Event.java +87 -67
  103. data/src/main/java/processing/event/KeyEvent.java +48 -41
  104. data/src/main/java/processing/event/MouseEvent.java +88 -113
  105. data/src/main/java/processing/event/TouchEvent.java +10 -6
  106. data/src/main/java/processing/javafx/PGraphicsFX2D.java +20 -345
  107. data/src/main/java/processing/javafx/PSurfaceFX.java +149 -121
  108. data/src/main/java/processing/net/Client.java +20 -20
  109. data/src/main/java/processing/net/Server.java +9 -9
  110. data/src/main/java/processing/opengl/FontTexture.java +286 -266
  111. data/src/main/java/processing/opengl/FrameBuffer.java +389 -377
  112. data/src/main/java/processing/opengl/LinePath.java +132 -89
  113. data/src/main/java/processing/opengl/LineStroker.java +588 -581
  114. data/src/main/java/processing/opengl/PGL.java +660 -567
  115. data/src/main/java/processing/opengl/PGraphics2D.java +408 -315
  116. data/src/main/java/processing/opengl/PGraphics3D.java +107 -72
  117. data/src/main/java/processing/opengl/PGraphicsOpenGL.java +12378 -12075
  118. data/src/main/java/processing/opengl/PJOGL.java +1753 -1670
  119. data/src/main/java/processing/opengl/PShader.java +369 -461
  120. data/src/main/java/processing/opengl/PShapeOpenGL.java +4678 -4580
  121. data/src/main/java/processing/opengl/PSurfaceJOGL.java +1114 -1027
  122. data/src/main/java/processing/opengl/Texture.java +1492 -1401
  123. data/src/main/java/processing/opengl/VertexBuffer.java +57 -55
  124. data/test/create_test.rb +21 -20
  125. data/test/deglut_spec_test.rb +4 -2
  126. data/test/helper_methods_test.rb +49 -20
  127. data/test/math_tool_test.rb +39 -32
  128. data/test/native_folder.rb +47 -0
  129. data/test/respond_to_test.rb +3 -2
  130. data/test/sketches/key_event.rb +2 -2
  131. data/test/sketches/library/my_library/my_library.rb +3 -0
  132. data/test/test_helper.rb +2 -0
  133. data/test/vecmath_spec_test.rb +35 -22
  134. data/vendors/Rakefile +35 -40
  135. metadata +47 -23
  136. data/library/simplex_noise/simplex_noise.rb +0 -3
  137. data/src/main/java/processing/opengl/shaders/LightVert-brcm.glsl +0 -154
  138. data/src/main/java/processing/opengl/shaders/LightVert-vc4.glsl +0 -154
  139. data/src/main/java/processing/opengl/shaders/TexLightVert-brcm.glsl +0 -160
  140. data/src/main/java/processing/opengl/shaders/TexLightVert-vc4.glsl +0 -160
@@ -13,187 +13,186 @@ 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
- 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();
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();
199
198
  }
@@ -1,3 +1,5 @@
1
+ /* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
2
+
1
3
  /*
2
4
  Part of the Processing project - http://processing.org
3
5
 
@@ -17,7 +19,8 @@
17
19
  Public License along with this library; if not, write to the
18
20
  Free Software Foundation, Inc., 59 Temple Place, Suite 330,
19
21
  Boston, MA 02111-1307 USA
20
- */
22
+ */
23
+
21
24
  package processing.data;
22
25
 
23
26
  import java.io.*;
@@ -36,9 +39,10 @@ import javax.xml.xpath.XPathFactory;
36
39
 
37
40
  import processing.core.PApplet;
38
41
 
42
+
39
43
  /**
40
- * This is the base class used for the Processing XML library, representing a
41
- * single node of an XML tree.
44
+ * This is the base class used for the Processing XML library,
45
+ * representing a single node of an XML tree.
42
46
  *
43
47
  * @webref data:composite
44
48
  * @see PApplet#loadXML(String)
@@ -47,28 +51,23 @@ import processing.core.PApplet;
47
51
  */
48
52
  public class XML implements Serializable {
49
53
 
50
- /**
51
- * The internal representation, a DOM node.
52
- */
53
- protected Node node;
54
+ /** The internal representation, a DOM node. */
55
+ protected Node node;
54
56
 
55
57
  // /** Cached locally because it's used often. */
56
58
  // protected String name;
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
- }
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
+
72
71
 
73
72
  // /**
74
73
  // * Begin parsing XML data passed in from a PApplet. This code
@@ -82,301 +81,324 @@ public class XML implements Serializable {
82
81
  // public XML(PApplet parent, String filename) throws IOException, ParserConfigurationException, SAXException {
83
82
  // this(parent.createReader(filename));
84
83
  // }
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
- }
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
- }
104
-
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
84
 
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
- }
164
85
 
165
- // without a validating DTD, this doesn't do anything since it doesn't know what is ignorable
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
166
171
  // factory.setIgnoringElementContentWhitespace(true);
167
- factory.setExpandEntityReferences(false);
172
+
173
+ factory.setExpandEntityReferences(false);
168
174
  // factory.setExpandEntityReferences(true);
169
175
 
170
176
  // factory.setCoalescing(true);
171
177
  // builderFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
172
- DocumentBuilder builder = factory.newDocumentBuilder();
178
+ DocumentBuilder builder = factory.newDocumentBuilder();
173
179
  // builder.setEntityResolver()
174
180
 
175
181
  // SAXParserFactory spf = SAXParserFactory.newInstance();
176
182
  // spf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
177
183
  // 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
- }
200
184
 
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);
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
+ }
216
197
  }
217
- }
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
- }
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));
236
243
  }
244
+ }
237
245
  }
246
+ }
238
247
 
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
- }
252
248
 
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
- }
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
+ }
269
+
259
270
 
260
271
  // protected boolean save(OutputStream output) {
261
272
  // return write(PApplet.createWriter(output));
262
273
  // }
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
- }
282
275
 
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() {
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() {
310
327
  // return name;
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);
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);
321
338
  // name = node.getNodeName();
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() {
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() {
380
402
  // NodeList children = node.getChildNodes();
381
403
  // int childCount = children.getLength();
382
404
  // String[] outgoing = new String[childCount];
@@ -386,21 +408,22 @@ public class XML implements Serializable {
386
408
  // outgoing[i] = kid.getNodeName();
387
409
  // } // otherwise just leave him null
388
410
  // }
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() {
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() {
404
427
  // NodeList children = node.getChildNodes();
405
428
  // int childCount = children.getLength();
406
429
  // XMLElement[] kids = new XMLElement[childCount];
@@ -409,185 +432,194 @@ public class XML implements Serializable {
409
432
  // kids[i] = new XMLElement(this, kid);
410
433
  // }
411
434
  // return kids;
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});
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);
554
504
  }
555
- return newbie;
556
- }
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
+ }
557
622
 
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
- }
591
623
 
592
624
  // /** Remove whitespace nodes. */
593
625
  // public void trim() {
@@ -636,447 +668,489 @@ public class XML implements Serializable {
636
668
  //// </xsl:template>
637
669
  //// </xsl:stylesheet>
638
670
  // }
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
- }
663
671
 
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
- }
673
672
 
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
- */
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
+ */
680
716
  // public String getAttribute(String name) {
681
717
  // return this.getAttribute(name, null);
682
718
  // }
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
- */
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
+ */
690
728
  // public String getAttribute(String name, String defaultValue) {
691
729
  // Node attr = node.getAttributes().getNamedItem(name);
692
730
  // return (attr == null) ? defaultValue : attr.getNodeValue();
693
731
  // }
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
- }
712
732
 
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
- }
720
733
 
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
- }
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
+ }
728
980
 
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
- }
736
981
 
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
- }
982
+ public void setFloatContent(float value) {
983
+ setContent(String.valueOf(value));
984
+ }
748
985
 
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
- }
756
986
 
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
- }
987
+ public void setLongContent(long value) {
988
+ setContent(String.valueOf(value));
989
+ }
768
990
 
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
- }
778
991
 
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
- }
992
+ public void setDoubleContent(double value) {
993
+ setContent(String.valueOf(value));
994
+ }
790
995
 
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
- }
887
- }
888
- return defaultValue;
889
- }
890
-
891
- public double getDoubleContent() {
892
- return getDoubleContent(0);
893
- }
894
-
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
- }
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;
902
1016
  }
903
- return defaultValue;
904
- }
1017
+ }
1018
+ Transformer transformer = factory.newTransformer();
905
1019
 
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
- }
913
-
914
- public void setIntContent(int value) {
915
- setContent(String.valueOf(value));
916
- }
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
- }
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
+ }
961
1027
 
962
1028
  // transformer.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM, "sample.dtd");
963
- transformer.setOutputProperty(OutputKeys.METHOD, "xml");
1029
+
1030
+ transformer.setOutputProperty(OutputKeys.METHOD, "xml");
964
1031
 
965
1032
  // transformer.setOutputProperty(OutputKeys.CDATA_SECTION_ELEMENTS, "yes"); // huh?
1033
+
966
1034
  // transformer.setOutputProperty(OutputKeys.DOCTYPE_PUBLIC,
967
1035
  // "-//W3C//DTD XHTML 1.0 Transitional//EN");
968
1036
  // transformer.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM,
969
1037
  // "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd");
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
- }
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
+ }
974
1043
 
975
1044
  // transformer.setOutputProperty(OutputKeys.ENCODING,"ISO-8859-1");
976
1045
  // transformer.setOutputProperty(OutputKeys.ENCODING,"UTF8");
977
- transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
1046
+ transformer.setOutputProperty(OutputKeys.ENCODING,"UTF-8");
978
1047
  // transformer.setOutputProperty(OutputKeys.CDATA_SECTION_ELEMENTS
979
1048
 
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");
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");
983
1052
 
984
1053
  // Properties p = transformer.getOutputProperties();
985
1054
  // for (Object key : p.keySet()) {
986
1055
  // System.out.println(key + " -> " + p.get(key));
987
1056
  // }
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);
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);
1003
1074
  // PApplet.println(tempLines);
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
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
1010
1081
  // PApplet.println("removing first line");
1011
- tempLines = PApplet.subset(tempLines, 1);
1012
- } else {
1082
+ tempLines = PApplet.subset(tempLines, 1);
1083
+ } else {
1013
1084
  // PApplet.println("removing part of first line");
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);
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);
1037
1109
  // DOMSource source = new DOMSource(node);
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();
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());
1059
1123
  }
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
- }
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
+ }
1082
1156
  }