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 d3b40cd9074d..9a7e6c539032 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}. + * + *
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.
+ * + *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:
+ * + *+ * 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 + *+ * + *
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.
+ * + *Self-closing tags (e.g. {@code
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.
+ * + * @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. + * + *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.
+ * + *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()}.
+ * + * @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. + * + *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.
* * @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); } }