001package org.jsoup.nodes;
002
003import org.jsoup.parser.ParseSettings;
004import org.jsoup.parser.Parser;
005import org.jspecify.annotations.Nullable;
006
007import java.io.IOException;
008import java.util.List;
009
010/**
011 A comment node.
012
013 @author Jonathan Hedley, jonathan@hedley.net */
014public class Comment extends LeafNode {
015    /**
016     Create a new comment node.
017     @param data The contents of the comment
018     */
019    public Comment(String data) {
020        super(data);
021    }
022
023    @Override public String nodeName() {
024        return "#comment";
025    }
026
027    /**
028     Get the contents of the comment.
029     @return comment content
030     */
031    public String getData() {
032        return coreValue();
033    }
034
035    public Comment setData(String data) {
036        coreValue(data);
037        return this;
038    }
039
040    @Override
041    void outerHtmlHead(Appendable accum, Document.OutputSettings out) throws IOException {
042        accum
043            .append("<!--")
044            .append(getData())
045            .append("-->");
046    }
047
048    @Override
049    public Comment clone() {
050        return (Comment) super.clone();
051    }
052
053    /**
054     * Check if this comment looks like an XML Declaration. This is the case when the HTML parser sees an XML
055     * declaration or processing instruction. Other than doctypes, those aren't part of HTML, and will be parsed as a
056     * bogus comment.
057     * @return true if it looks like, maybe, it's an XML Declaration.
058     * @see #asXmlDeclaration()
059     */
060    public boolean isXmlDeclaration() {
061        String data = getData();
062        return isXmlDeclarationData(data);
063    }
064
065    private static boolean isXmlDeclarationData(String data) {
066        return (data.length() > 1 && (data.startsWith("!") || data.startsWith("?")));
067    }
068
069    /**
070     * Attempt to cast this comment to an XML Declaration node.
071     * @return an XML declaration if it could be parsed as one, null otherwise.
072     * @see #isXmlDeclaration()
073     */
074    public @Nullable XmlDeclaration asXmlDeclaration() {
075        String fragment = "<" + getData() + ">";
076        Parser parser = Parser.xmlParser();
077        List<Node> nodes = parser.parseFragmentInput(fragment, null, "");
078        if (!nodes.isEmpty() && nodes.get(0) instanceof XmlDeclaration)
079            return (XmlDeclaration) nodes.get(0);
080        return null;
081    }
082}