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 super(name); 023 this.isProcessingInstruction = isProcessingInstruction; 024 } 025 026 @Override public String nodeName() { 027 return "#declaration"; 028 } 029 030 /** 031 * Get the name of this declaration. 032 * @return name of this declaration. 033 */ 034 public String name() { 035 return coreValue(); 036 } 037 038 /** 039 * Get the unencoded XML declaration. 040 * @return XML declaration 041 */ 042 public String getWholeDeclaration() { 043 StringBuilder sb = StringUtil.borrowBuilder(); 044 try { 045 getWholeDeclaration(sb, new Document.OutputSettings()); 046 } catch (IOException e) { 047 throw new SerializationException(e); 048 } 049 return StringUtil.releaseBuilder(sb).trim(); 050 } 051 052 private void getWholeDeclaration(Appendable accum, Document.OutputSettings out) throws IOException { 053 for (Attribute attribute : attributes()) { 054 String key = attribute.getKey(); 055 String val = attribute.getValue(); 056 if (!key.equals(nodeName())) { // skips coreValue (name) 057 accum.append(' '); 058 // basically like Attribute, but skip empty vals in XML 059 accum.append(key); 060 if (!val.isEmpty()) { 061 accum.append("=\""); 062 Entities.escape(accum, val, out, Entities.ForAttribute); 063 accum.append('"'); 064 } 065 } 066 } 067 } 068 069 @Override 070 void outerHtmlHead(Appendable accum, int depth, Document.OutputSettings out) throws IOException { 071 accum 072 .append("<") 073 .append(isProcessingInstruction ? "!" : "?") 074 .append(coreValue()); 075 getWholeDeclaration(accum, out); 076 accum 077 .append(isProcessingInstruction ? "!" : "?") 078 .append(">"); 079 } 080 081 @Override 082 void outerHtmlTail(Appendable accum, int depth, Document.OutputSettings out) { 083 } 084 085 @Override 086 public String toString() { 087 return outerHtml(); 088 } 089 090 @Override 091 public XmlDeclaration clone() { 092 return (XmlDeclaration) super.clone(); 093 } 094}