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