001package org.jsoup.nodes;
002
003import org.jsoup.SerializationException;
004import org.jsoup.helper.Validate;
005
006import java.io.IOException;
007
008/**
009 * An XML Declaration.
010 */
011public class XmlDeclaration extends LeafNode {
012    // todo this impl isn't really right, the data shouldn't be attributes, just a run of text after the name
013    private final boolean isProcessingInstruction; // <! if true, <? if false, declaration (and last data char should be ?)
014
015    /**
016     * Create a new XML declaration
017     * @param name of declaration
018     * @param isProcessingInstruction is processing instruction
019     */
020    public XmlDeclaration(String name, boolean isProcessingInstruction) {
021        Validate.notNull(name);
022        value = name;
023        this.isProcessingInstruction = isProcessingInstruction;
024    }
025
026    /**
027     * Create a new XML declaration
028     * @param name of declaration
029     * @param baseUri Leaf Nodes don't have base URIs; they inherit from their Element
030     * @param isProcessingInstruction is processing instruction
031     * @see XmlDeclaration#XmlDeclaration(String, boolean)
032     * @deprecated
033     */
034    public XmlDeclaration(String name, String baseUri, boolean isProcessingInstruction) {
035        this(name, isProcessingInstruction);
036    }
037
038    public String nodeName() {
039        return "#declaration";
040    }
041
042    /**
043     * Get the name of this declaration.
044     * @return name of this declaration.
045     */
046    public String name() {
047        return coreValue();
048    }
049
050    /**
051     * Get the unencoded XML declaration.
052     * @return XML declaration
053     */
054    public String getWholeDeclaration() {
055        StringBuilder sb = new StringBuilder();
056        try {
057            getWholeDeclaration(sb, new Document.OutputSettings());
058        } catch (IOException e) {
059            throw new SerializationException(e);
060        }
061        return sb.toString().trim();
062    }
063
064    private void getWholeDeclaration(Appendable accum, Document.OutputSettings out) throws IOException {
065        for (Attribute attribute : attributes()) {
066            if (!attribute.getKey().equals(nodeName())) { // skips coreValue (name)
067                accum.append(' ');
068                attribute.html(accum, out);
069            }
070        }
071    }
072
073    void outerHtmlHead(Appendable accum, int depth, Document.OutputSettings out) throws IOException {
074        accum
075            .append("<")
076            .append(isProcessingInstruction ? "!" : "?")
077            .append(coreValue());
078        getWholeDeclaration(accum, out);
079        accum
080            .append(isProcessingInstruction ? "!" : "?")
081            .append(">");
082    }
083
084    void outerHtmlTail(Appendable accum, int depth, Document.OutputSettings out) {
085    }
086
087    @Override
088    public String toString() {
089        return outerHtml();
090    }
091}