This is an automated email from the ASF dual-hosted git repository.
gnodet pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/maven.git
The following commit(s) were added to refs/heads/master by this push:
new b9d73e0acb Add comprehensive Javadoc to XmlNodeBuilder (#11925)
b9d73e0acb is described below
commit b9d73e0acb0f39b604795fb0d1cea8e13bb00a79
Author: Uğur Tafralı <[email protected]>
AuthorDate: Thu May 21 00:23:06 2026 +0300
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
---
.../apache/maven/internal/xml/XmlNodeBuilder.java | 174 ++++++++++++++++++---
1 file changed, 154 insertions(+), 20 deletions(-)
diff --git
a/impl/maven-xml/src/main/java/org/apache/maven/internal/xml/XmlNodeBuilder.java
b/impl/maven-xml/src/main/java/org/apache/maven/internal/xml/XmlNodeBuilder.java
index d3b40cd907..9a7e6c5390 100644
---
a/impl/maven-xml/src/main/java/org/apache/maven/internal/xml/XmlNodeBuilder.java
+++
b/impl/maven-xml/src/main/java/org/apache/maven/internal/xml/XmlNodeBuilder.java
@@ -32,34 +32,108 @@
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
/**
- * All methods in this class attempt to fully parse the XML.
- * The caller is responsible for closing {@code InputStream} and {@code
Reader} arguments.
+ * Builds an {@link XmlNodeImpl} DOM tree from XML input using an {@link
XmlPullParser}.
+ *
+ * <p>All {@code build} methods in this class parse a single XML document
element (including
+ * its children) from the input and return it as an {@link XmlNodeImpl}. The
caller is
+ * responsible for closing any {@link InputStream} or {@link Reader} passed to
these methods.</p>
+ *
+ * <h2>Multi-document stream reading</h2>
+ *
+ * <p>When the underlying {@link Reader} or {@link InputStream} contains
multiple concatenated
+ * XML documents, each call to {@code build} consumes exactly one root element
and its children.
+ * The stream position is left immediately after the closing tag of that
element, so a subsequent
+ * call to {@code build} with a new parser wrapping the same reader will parse
the next document.
+ * For example, given a reader over the concatenation of two identical
documents:</p>
+ *
+ * <pre>
+ * String doc = "<?xml
version='1.0'?><doc><child>foo</child></doc>";
+ * Reader r = new StringReader(doc + doc);
+ * XmlNode first = XmlService.read(r); // reads the first <doc>
+ * XmlNode second = XmlService.read(r); // reads the second <doc>
+ * // first.equals(second) is true
+ * </pre>
+ *
+ * <h2>Whitespace trimming</h2>
+ *
+ * <p>By default, text content is trimmed of leading and trailing whitespace.
This can be
+ * disabled by passing {@code trim = false}, or on a per-element basis by
setting the
+ * {@code xml:space="preserve"} attribute on an element.</p>
+ *
+ * <h2>Empty vs. self-closing elements</h2>
+ *
+ * <p>Self-closing tags (e.g. {@code <item/>}) produce a node whose value is
{@code null}.
+ * An element with an explicit open and close tag but no content (e.g. {@code
<item></item>})
+ * produces a node whose value is the empty string {@code ""}.</p>
+ *
+ * <h2>Child elements vs. text content</h2>
+ *
+ * <p>If an element contains child elements, the resulting node carries the
children and its
+ * text value is {@code null}, even if there is interleaved text content. If
an element
+ * contains only text (no child elements), the node carries the text value and
has no
+ * children.</p>
+ *
+ * @deprecated Use {@link org.apache.maven.api.xml.XmlService} instead.
*/
@Deprecated
public class XmlNodeBuilder {
private static final boolean DEFAULT_TRIM = true;
+ /**
+ * Builds an XML node tree from the given reader, trimming whitespace by
default and
+ * without tracking input locations.
+ *
+ * @param reader the reader to parse XML from
+ * @return the parsed XML node tree
+ * @throws XmlPullParserException if the XML is not well-formed
+ * @throws IOException if an I/O error occurs while reading
+ */
public static XmlNodeImpl build(Reader reader) throws
XmlPullParserException, IOException {
return build(reader, (InputLocationBuilder) null);
}
/**
- * @param reader the reader
- * @param locationBuilder the builder
+ * Builds an XML node tree from the given reader, trimming whitespace by
default.
+ *
+ * @param reader the reader to parse XML from
+ * @param locationBuilder optional builder for recording input locations
of parsed elements,
+ * or {@code null} to skip location tracking
+ * @return the parsed XML node tree
+ * @throws XmlPullParserException if the XML is not well-formed
+ * @throws IOException if an I/O error occurs while reading
* @since 3.2.0
- * @return DOM
- * @throws XmlPullParserException XML well-formedness error
- * @throws IOException I/O error reading file or stream
*/
public static XmlNodeImpl build(Reader reader, InputLocationBuilder
locationBuilder)
throws XmlPullParserException, IOException {
return build(reader, DEFAULT_TRIM, locationBuilder);
}
+ /**
+ * Builds an XML node tree from the given input stream, trimming
whitespace by default.
+ *
+ * @param is the input stream to parse XML from
+ * @param encoding the character encoding of the stream (e.g. {@code
"UTF-8"}),
+ * or {@code null} to let the parser detect it
+ * @return the parsed XML node tree
+ * @throws XmlPullParserException if the XML is not well-formed
+ * @throws IOException if an I/O error occurs while reading
+ */
public static XmlNodeImpl build(InputStream is, String encoding) throws
XmlPullParserException, IOException {
return build(is, encoding, DEFAULT_TRIM);
}
+ /**
+ * Builds an XML node tree from the given input stream.
+ *
+ * @param is the input stream to parse XML from
+ * @param encoding the character encoding of the stream (e.g. {@code
"UTF-8"}),
+ * or {@code null} to let the parser detect it
+ * @param trim if {@code true}, leading and trailing whitespace is removed
from text
+ * content unless the element has {@code xml:space="preserve"}
+ * @return the parsed XML node tree
+ * @throws XmlPullParserException if the XML is not well-formed
+ * @throws IOException if an I/O error occurs while reading
+ */
public static XmlNodeImpl build(InputStream is, String encoding, boolean
trim)
throws XmlPullParserException, IOException {
XmlPullParser parser = new MXParser();
@@ -67,18 +141,32 @@ public static XmlNodeImpl build(InputStream is, String
encoding, boolean trim)
return build(parser, trim);
}
+ /**
+ * Builds an XML node tree from the given reader without location tracking.
+ *
+ * @param reader the reader to parse XML from
+ * @param trim if {@code true}, leading and trailing whitespace is removed
from text
+ * content unless the element has {@code xml:space="preserve"}
+ * @return the parsed XML node tree
+ * @throws XmlPullParserException if the XML is not well-formed
+ * @throws IOException if an I/O error occurs while reading
+ */
public static XmlNodeImpl build(Reader reader, boolean trim) throws
XmlPullParserException, IOException {
return build(reader, trim, null);
}
/**
- * @param reader the reader
- * @param trim to trim
- * @param locationBuilder the builder
+ * Builds an XML node tree from the given reader.
+ *
+ * @param reader the reader to parse XML from
+ * @param trim if {@code true}, leading and trailing whitespace is removed
from text
+ * content unless the element has {@code xml:space="preserve"}
+ * @param locationBuilder optional builder for recording input locations
of parsed elements,
+ * or {@code null} to skip location tracking
+ * @return the parsed XML node tree
+ * @throws XmlPullParserException if the XML is not well-formed
+ * @throws IOException if an I/O error occurs while reading
* @since 3.2.0
- * @return DOM
- * @throws XmlPullParserException XML well-formedness error
- * @throws IOException I/O error reading file or stream
*/
public static XmlNodeImpl build(Reader reader, boolean trim,
InputLocationBuilder locationBuilder)
throws XmlPullParserException, IOException {
@@ -87,22 +175,57 @@ public static XmlNodeImpl build(Reader reader, boolean
trim, InputLocationBuilde
return build(parser, trim, locationBuilder);
}
+ /**
+ * Builds an XML node tree from the given pull parser, trimming whitespace
by default and
+ * without tracking input locations.
+ *
+ * @param parser the pull parser positioned at or before the root
element's start tag
+ * @return the parsed XML node tree
+ * @throws XmlPullParserException if the XML is not well-formed
+ * @throws IOException if an I/O error occurs while reading
+ */
public static XmlNodeImpl build(XmlPullParser parser) throws
XmlPullParserException, IOException {
return build(parser, DEFAULT_TRIM);
}
+ /**
+ * Builds an XML node tree from the given pull parser without location
tracking.
+ *
+ * @param parser the pull parser positioned at or before the root
element's start tag
+ * @param trim if {@code true}, leading and trailing whitespace is removed
from text
+ * content unless the element has {@code xml:space="preserve"}
+ * @return the parsed XML node tree
+ * @throws XmlPullParserException if the XML is not well-formed
+ * @throws IOException if an I/O error occurs while reading
+ */
public static XmlNodeImpl build(XmlPullParser parser, boolean trim) throws
XmlPullParserException, IOException {
return build(parser, trim, null);
}
/**
+ * Core parsing method. Builds an XML node tree from the given pull parser.
+ *
+ * <p>Parsing begins at the parser's current event and consumes tokens
through the
+ * matching end tag of the first start tag encountered. When this method
returns, the
+ * parser is positioned immediately after that end tag, so the caller (or
a subsequent
+ * {@code build} call) can continue reading the same stream.</p>
+ *
+ * <p>Child elements are parsed recursively. If the element contains only
text content
+ * (no child elements), the text is stored as the node's value. If child
elements are
+ * present, the text value is {@code null} and children are accessible via
+ * {@link XmlNodeImpl#getChildren()}.</p>
+ *
+ * @param parser the pull parser positioned at or before the root
element's start tag
+ * @param trim if {@code true}, leading and trailing whitespace is removed
from text
+ * content unless the element has {@code xml:space="preserve"}
+ * @param locationBuilder optional builder for recording input locations
of parsed elements,
+ * or {@code null} to skip location tracking
+ * @return the parsed XML node tree
+ * @throws XmlPullParserException if the XML is not well-formed
+ * @throws IOException if an I/O error occurs while reading
+ * @throws IllegalStateException if the end of the document is reached
before the root
+ * element's end tag is found
* @since 3.2.0
- * @param locationBuilder builder
- * @param parser the parser
- * @param trim do trim
- * @return DOM
- * @throws XmlPullParserException XML well-formedness error
- * @throws IOException I/O error reading file or stream
*/
public static XmlNodeImpl build(XmlPullParser parser, boolean trim,
InputLocationBuilder locationBuilder)
throws XmlPullParserException, IOException {
@@ -157,11 +280,22 @@ public static XmlNodeImpl build(XmlPullParser parser,
boolean trim, InputLocatio
}
/**
- * Input location builder interface, to be implemented to choose how to
store data.
+ * Callback interface for creating input location objects during parsing.
+ *
+ * <p>Implementations determine how source location information (line
number, column, etc.)
+ * is captured and stored for each parsed element. The returned object is
attached to the
+ * resulting {@link XmlNodeImpl} as its location.</p>
*
* @since 3.2.0
*/
public interface InputLocationBuilder {
+ /**
+ * Creates an input location object from the parser's current position.
+ *
+ * @param parser the pull parser, positioned at the start tag of the
element being built
+ * @return an object representing the source location, or {@code null}
if location
+ * tracking is not needed for this element
+ */
Object toInputLocation(XmlPullParser parser);
}
}