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; 008 009/** 010 A comment node. 011 012 @author Jonathan Hedley, jonathan@hedley.net */ 013public class Comment extends LeafNode { 014 /** 015 Create a new comment node. 016 @param data The contents of the comment 017 */ 018 public Comment(String data) { 019 super(data); 020 } 021 022 @Override public String nodeName() { 023 return "#comment"; 024 } 025 026 /** 027 Get the contents of the comment. 028 @return comment content 029 */ 030 public String getData() { 031 return coreValue(); 032 } 033 034 public Comment setData(String data) { 035 coreValue(data); 036 return this; 037 } 038 039 @Override 040 void outerHtmlHead(Appendable accum, int depth, Document.OutputSettings out) throws IOException { 041 if (out.prettyPrint() && ((isEffectivelyFirst() && parentNode instanceof Element && ((Element) parentNode).tag().formatAsBlock()) || (out.outline() ))) 042 indent(accum, depth, out); 043 accum 044 .append("<!--") 045 .append(getData()) 046 .append("-->"); 047 } 048 049 @Override 050 void outerHtmlTail(Appendable accum, int depth, Document.OutputSettings out) {} 051 052 @Override 053 public Comment clone() { 054 return (Comment) super.clone(); 055 } 056 057 /** 058 * Check if this comment looks like an XML Declaration. 059 * @return true if it looks like, maybe, it's an XML Declaration. 060 */ 061 public boolean isXmlDeclaration() { 062 String data = getData(); 063 return isXmlDeclarationData(data); 064 } 065 066 private static boolean isXmlDeclarationData(String data) { 067 return (data.length() > 1 && (data.startsWith("!") || data.startsWith("?"))); 068 } 069 070 /** 071 * Attempt to cast this comment to an XML Declaration node. 072 * @return an XML declaration if it could be parsed as one, null otherwise. 073 */ 074 public @Nullable XmlDeclaration asXmlDeclaration() { 075 String data = getData(); 076 077 XmlDeclaration decl = null; 078 String declContent = data.substring(1, data.length() - 1); 079 // make sure this bogus comment is not immediately followed by another, treat as comment if so 080 if (isXmlDeclarationData(declContent)) 081 return null; 082 083 String fragment = "<" + declContent + ">"; 084 // use the HTML parser not XML, so we don't get into a recursive XML Declaration on contrived data 085 Document doc = Parser.htmlParser().settings(ParseSettings.preserveCase).parseInput(fragment, baseUri()); 086 if (doc.body().childrenSize() > 0) { 087 Element el = doc.body().child(0); 088 decl = new XmlDeclaration(NodeUtils.parser(doc).settings().normalizeTag(el.tagName()), data.startsWith("!")); 089 decl.attributes().addAll(el.attributes()); 090 } 091 return decl; 092 } 093}