Skip to content

Commit b9d73e0

Browse files
authored
Add comprehensive Javadoc to XmlNodeBuilder (#11925)
Document the multi-document stream reading behavior, whitespace trimming semantics, empty vs self-closing element handling, and child-vs-text-value semantics. Also document all public build() overloads and the InputLocationBuilder interface. Closes #11526
1 parent 5e5bf75 commit b9d73e0

1 file changed

Lines changed: 154 additions & 20 deletions

File tree

impl/maven-xml/src/main/java/org/apache/maven/internal/xml/XmlNodeBuilder.java

Lines changed: 154 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -32,53 +32,141 @@
3232
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
3333

3434
/**
35-
* All methods in this class attempt to fully parse the XML.
36-
* The caller is responsible for closing {@code InputStream} and {@code Reader} arguments.
35+
* Builds an {@link XmlNodeImpl} DOM tree from XML input using an {@link XmlPullParser}.
36+
*
37+
* <p>All {@code build} methods in this class parse a single XML document element (including
38+
* its children) from the input and return it as an {@link XmlNodeImpl}. The caller is
39+
* responsible for closing any {@link InputStream} or {@link Reader} passed to these methods.</p>
40+
*
41+
* <h2>Multi-document stream reading</h2>
42+
*
43+
* <p>When the underlying {@link Reader} or {@link InputStream} contains multiple concatenated
44+
* XML documents, each call to {@code build} consumes exactly one root element and its children.
45+
* The stream position is left immediately after the closing tag of that element, so a subsequent
46+
* call to {@code build} with a new parser wrapping the same reader will parse the next document.
47+
* For example, given a reader over the concatenation of two identical documents:</p>
48+
*
49+
* <pre>
50+
* String doc = "&lt;?xml version='1.0'?&gt;&lt;doc&gt;&lt;child&gt;foo&lt;/child&gt;&lt;/doc&gt;";
51+
* Reader r = new StringReader(doc + doc);
52+
* XmlNode first = XmlService.read(r); // reads the first &lt;doc&gt;
53+
* XmlNode second = XmlService.read(r); // reads the second &lt;doc&gt;
54+
* // first.equals(second) is true
55+
* </pre>
56+
*
57+
* <h2>Whitespace trimming</h2>
58+
*
59+
* <p>By default, text content is trimmed of leading and trailing whitespace. This can be
60+
* disabled by passing {@code trim = false}, or on a per-element basis by setting the
61+
* {@code xml:space="preserve"} attribute on an element.</p>
62+
*
63+
* <h2>Empty vs. self-closing elements</h2>
64+
*
65+
* <p>Self-closing tags (e.g. {@code <item/>}) produce a node whose value is {@code null}.
66+
* An element with an explicit open and close tag but no content (e.g. {@code <item></item>})
67+
* produces a node whose value is the empty string {@code ""}.</p>
68+
*
69+
* <h2>Child elements vs. text content</h2>
70+
*
71+
* <p>If an element contains child elements, the resulting node carries the children and its
72+
* text value is {@code null}, even if there is interleaved text content. If an element
73+
* contains only text (no child elements), the node carries the text value and has no
74+
* children.</p>
75+
*
76+
* @deprecated Use {@link org.apache.maven.api.xml.XmlService} instead.
3777
*/
3878
@Deprecated
3979
public class XmlNodeBuilder {
4080
private static final boolean DEFAULT_TRIM = true;
4181

82+
/**
83+
* Builds an XML node tree from the given reader, trimming whitespace by default and
84+
* without tracking input locations.
85+
*
86+
* @param reader the reader to parse XML from
87+
* @return the parsed XML node tree
88+
* @throws XmlPullParserException if the XML is not well-formed
89+
* @throws IOException if an I/O error occurs while reading
90+
*/
4291
public static XmlNodeImpl build(Reader reader) throws XmlPullParserException, IOException {
4392
return build(reader, (InputLocationBuilder) null);
4493
}
4594

4695
/**
47-
* @param reader the reader
48-
* @param locationBuilder the builder
96+
* Builds an XML node tree from the given reader, trimming whitespace by default.
97+
*
98+
* @param reader the reader to parse XML from
99+
* @param locationBuilder optional builder for recording input locations of parsed elements,
100+
* or {@code null} to skip location tracking
101+
* @return the parsed XML node tree
102+
* @throws XmlPullParserException if the XML is not well-formed
103+
* @throws IOException if an I/O error occurs while reading
49104
* @since 3.2.0
50-
* @return DOM
51-
* @throws XmlPullParserException XML well-formedness error
52-
* @throws IOException I/O error reading file or stream
53105
*/
54106
public static XmlNodeImpl build(Reader reader, InputLocationBuilder locationBuilder)
55107
throws XmlPullParserException, IOException {
56108
return build(reader, DEFAULT_TRIM, locationBuilder);
57109
}
58110

111+
/**
112+
* Builds an XML node tree from the given input stream, trimming whitespace by default.
113+
*
114+
* @param is the input stream to parse XML from
115+
* @param encoding the character encoding of the stream (e.g. {@code "UTF-8"}),
116+
* or {@code null} to let the parser detect it
117+
* @return the parsed XML node tree
118+
* @throws XmlPullParserException if the XML is not well-formed
119+
* @throws IOException if an I/O error occurs while reading
120+
*/
59121
public static XmlNodeImpl build(InputStream is, String encoding) throws XmlPullParserException, IOException {
60122
return build(is, encoding, DEFAULT_TRIM);
61123
}
62124

125+
/**
126+
* Builds an XML node tree from the given input stream.
127+
*
128+
* @param is the input stream to parse XML from
129+
* @param encoding the character encoding of the stream (e.g. {@code "UTF-8"}),
130+
* or {@code null} to let the parser detect it
131+
* @param trim if {@code true}, leading and trailing whitespace is removed from text
132+
* content unless the element has {@code xml:space="preserve"}
133+
* @return the parsed XML node tree
134+
* @throws XmlPullParserException if the XML is not well-formed
135+
* @throws IOException if an I/O error occurs while reading
136+
*/
63137
public static XmlNodeImpl build(InputStream is, String encoding, boolean trim)
64138
throws XmlPullParserException, IOException {
65139
XmlPullParser parser = new MXParser();
66140
parser.setInput(is, encoding);
67141
return build(parser, trim);
68142
}
69143

144+
/**
145+
* Builds an XML node tree from the given reader without location tracking.
146+
*
147+
* @param reader the reader to parse XML from
148+
* @param trim if {@code true}, leading and trailing whitespace is removed from text
149+
* content unless the element has {@code xml:space="preserve"}
150+
* @return the parsed XML node tree
151+
* @throws XmlPullParserException if the XML is not well-formed
152+
* @throws IOException if an I/O error occurs while reading
153+
*/
70154
public static XmlNodeImpl build(Reader reader, boolean trim) throws XmlPullParserException, IOException {
71155
return build(reader, trim, null);
72156
}
73157

74158
/**
75-
* @param reader the reader
76-
* @param trim to trim
77-
* @param locationBuilder the builder
159+
* Builds an XML node tree from the given reader.
160+
*
161+
* @param reader the reader to parse XML from
162+
* @param trim if {@code true}, leading and trailing whitespace is removed from text
163+
* content unless the element has {@code xml:space="preserve"}
164+
* @param locationBuilder optional builder for recording input locations of parsed elements,
165+
* or {@code null} to skip location tracking
166+
* @return the parsed XML node tree
167+
* @throws XmlPullParserException if the XML is not well-formed
168+
* @throws IOException if an I/O error occurs while reading
78169
* @since 3.2.0
79-
* @return DOM
80-
* @throws XmlPullParserException XML well-formedness error
81-
* @throws IOException I/O error reading file or stream
82170
*/
83171
public static XmlNodeImpl build(Reader reader, boolean trim, InputLocationBuilder locationBuilder)
84172
throws XmlPullParserException, IOException {
@@ -87,22 +175,57 @@ public static XmlNodeImpl build(Reader reader, boolean trim, InputLocationBuilde
87175
return build(parser, trim, locationBuilder);
88176
}
89177

178+
/**
179+
* Builds an XML node tree from the given pull parser, trimming whitespace by default and
180+
* without tracking input locations.
181+
*
182+
* @param parser the pull parser positioned at or before the root element's start tag
183+
* @return the parsed XML node tree
184+
* @throws XmlPullParserException if the XML is not well-formed
185+
* @throws IOException if an I/O error occurs while reading
186+
*/
90187
public static XmlNodeImpl build(XmlPullParser parser) throws XmlPullParserException, IOException {
91188
return build(parser, DEFAULT_TRIM);
92189
}
93190

191+
/**
192+
* Builds an XML node tree from the given pull parser without location tracking.
193+
*
194+
* @param parser the pull parser positioned at or before the root element's start tag
195+
* @param trim if {@code true}, leading and trailing whitespace is removed from text
196+
* content unless the element has {@code xml:space="preserve"}
197+
* @return the parsed XML node tree
198+
* @throws XmlPullParserException if the XML is not well-formed
199+
* @throws IOException if an I/O error occurs while reading
200+
*/
94201
public static XmlNodeImpl build(XmlPullParser parser, boolean trim) throws XmlPullParserException, IOException {
95202
return build(parser, trim, null);
96203
}
97204

98205
/**
206+
* Core parsing method. Builds an XML node tree from the given pull parser.
207+
*
208+
* <p>Parsing begins at the parser's current event and consumes tokens through the
209+
* matching end tag of the first start tag encountered. When this method returns, the
210+
* parser is positioned immediately after that end tag, so the caller (or a subsequent
211+
* {@code build} call) can continue reading the same stream.</p>
212+
*
213+
* <p>Child elements are parsed recursively. If the element contains only text content
214+
* (no child elements), the text is stored as the node's value. If child elements are
215+
* present, the text value is {@code null} and children are accessible via
216+
* {@link XmlNodeImpl#getChildren()}.</p>
217+
*
218+
* @param parser the pull parser positioned at or before the root element's start tag
219+
* @param trim if {@code true}, leading and trailing whitespace is removed from text
220+
* content unless the element has {@code xml:space="preserve"}
221+
* @param locationBuilder optional builder for recording input locations of parsed elements,
222+
* or {@code null} to skip location tracking
223+
* @return the parsed XML node tree
224+
* @throws XmlPullParserException if the XML is not well-formed
225+
* @throws IOException if an I/O error occurs while reading
226+
* @throws IllegalStateException if the end of the document is reached before the root
227+
* element's end tag is found
99228
* @since 3.2.0
100-
* @param locationBuilder builder
101-
* @param parser the parser
102-
* @param trim do trim
103-
* @return DOM
104-
* @throws XmlPullParserException XML well-formedness error
105-
* @throws IOException I/O error reading file or stream
106229
*/
107230
public static XmlNodeImpl build(XmlPullParser parser, boolean trim, InputLocationBuilder locationBuilder)
108231
throws XmlPullParserException, IOException {
@@ -157,11 +280,22 @@ public static XmlNodeImpl build(XmlPullParser parser, boolean trim, InputLocatio
157280
}
158281

159282
/**
160-
* Input location builder interface, to be implemented to choose how to store data.
283+
* Callback interface for creating input location objects during parsing.
284+
*
285+
* <p>Implementations determine how source location information (line number, column, etc.)
286+
* is captured and stored for each parsed element. The returned object is attached to the
287+
* resulting {@link XmlNodeImpl} as its location.</p>
161288
*
162289
* @since 3.2.0
163290
*/
164291
public interface InputLocationBuilder {
292+
/**
293+
* Creates an input location object from the parser's current position.
294+
*
295+
* @param parser the pull parser, positioned at the start tag of the element being built
296+
* @return an object representing the source location, or {@code null} if location
297+
* tracking is not needed for this element
298+
*/
165299
Object toInputLocation(XmlPullParser parser);
166300
}
167301
}

0 commit comments

Comments
 (0)