Java 문자열에서 HTML을 제거하는 좋은 방법이 있습니까? 간단한 정규식
replaceAll("\\<.*?>","")
작동하지만 &
두 개의 꺾쇠 괄호 사이에 HTML이 아닌 것과 같은 것이 올바르게 변환되지 않습니다 (즉 .*?
, 정규 표현식에서가 사라집니다).
Java 문자열에서 HTML을 제거하는 좋은 방법이 있습니까? 간단한 정규식
replaceAll("\\<.*?>","")
작동하지만 &
두 개의 꺾쇠 괄호 사이에 HTML이 아닌 것과 같은 것이 올바르게 변환되지 않습니다 (즉 .*?
, 정규 표현식에서가 사라집니다).
답변:
정규식 대신 HTML 파서를 사용하십시오. 이것은 Jsoup으로 간단 합니다.
public static String html2text(String html) {
return Jsoup.parse(html).text();
}
Jsoup은 또한 사용자 정의 가능한 화이트리스트에 대한 HTML 태그 제거 를 지원합니다 . 예를 들어 <b>
, <i>
및 을 허용하려는 경우 매우 유용합니다 <u>
.
Jsoup#clean()
대신 사용하고 싶습니다 .
<p>Lorem ipsum 1 < 3 dolor sit amet</p>
. 다시 말하지만 HTML은 일반 언어가 아닙니다 . 모든 사람들이 실제 파서를 사용하는 대신 관심있는 부분을 파싱하기 위해 정규 표현식을 계속 던지는 이유는 완전히 저쪽에 있습니다.
Jsoup.clean(unsafeString, "", Whitelist.none(), new OutputSettings().prettyPrint(false));
Android 용으로 작성 하는 경우이 작업을 수행 할 수 있습니다.
android.text.Html.fromHtml(instruction).toString()
사용자가 입력 <b>hey!</b>
하면 <b>hey!</b>
또는 을 표시 hey!
하시겠습니까? 첫 번째 경우보다 작고 이스케이프 처리하고 앰퍼샌드 (및 선택적으로 따옴표)를 html로 인코딩하면 괜찮습니다. 두 번째 옵션을 구현하기 위해 코드를 수정하면 다음과 같습니다.
replaceAll("\\<[^>]*>","")
그러나 사용자가와 같이 잘못된 것을 입력하면 문제가 발생합니다 <bhey!</b>
.
"dirty"html 입력을 구문 분석하고 텍스트를 유지하면서 태그를 제거하는 방법을 제공 하는 JTidy 를 확인할 수도 있습니다 .
html을 제거하려고 할 때의 문제는 브라우저에 매우 관대 한 파서가 있고 찾을 수있는 라이브러리보다 관대하다는 것입니다. 따라서 모든 태그를 제거하는 것이 최선이더라도 (위의 replace 메소드, DOM 라이브러리 또는 JTidy 사용) 당신은 것입니다 여전히 귀하의 출력 안전을 유지하기 위해 남아있는 HTML 특수 문자를 인코딩 할 수 있는지 확인해야합니다.
다른 방법은 javax.swing.text.html.HTMLEditorKit 를 사용하여 텍스트를 추출하는 것입니다.
import java.io.*;
import javax.swing.text.html.*;
import javax.swing.text.html.parser.*;
public class Html2Text extends HTMLEditorKit.ParserCallback {
StringBuffer s;
public Html2Text() {
}
public void parse(Reader in) throws IOException {
s = new StringBuffer();
ParserDelegator delegator = new ParserDelegator();
// the third parameter is TRUE to ignore charset directive
delegator.parse(in, this, Boolean.TRUE);
}
public void handleText(char[] text, int pos) {
s.append(text);
}
public String getText() {
return s.toString();
}
public static void main(String[] args) {
try {
// the HTML to convert
FileReader in = new FileReader("java-new.html");
Html2Text parser = new Html2Text();
parser.parse(in);
in.close();
System.out.println(parser.getText());
} catch (Exception e) {
e.printStackTrace();
}
}
}
Jericho를 사용하면 매우 간단 하며 일부 서식 (예 : 줄 바꿈 및 링크)을 유지할 수 있습니다.
Source htmlSource = new Source(htmlText);
Segment htmlSeg = new Segment(htmlSource, 0, htmlSource.length());
Renderer htmlRend = new Renderer(htmlSeg);
System.out.println(htmlRend.toString());
단순히 일을 허용 대답은 Jsoup.parse(html).text()
(JSoup 1.7.3 포함)이 잠재적 인 문제를 가지고 :
<script>
를<script>
이것을 사용하여 XSS로부터 보호한다면, 이것은 약간 성가신 일입니다. 다음은 JSoup과 Apache StringEscapeUtils를 모두 사용하여 개선 된 솔루션에 대한 최고의 정보입니다.
// breaks multi-level of escaping, preventing &lt;script&gt; to be rendered as <script>
String replace = input.replace("&", "");
// decode any encoded html, preventing <script> to be rendered as <script>
String html = StringEscapeUtils.unescapeHtml(replace);
// remove all html tags, but maintain line breaks
String clean = Jsoup.clean(html, "", Whitelist.none(), new Document.OutputSettings().prettyPrint(false));
// decode html again to convert character entities back into text
return StringEscapeUtils.unescapeHtml(clean);
마지막 단계는 출력을 일반 텍스트로 사용해야하기 때문입니다. HTML 출력 만 필요한 경우이를 제거 할 수 있어야합니다.
다음은 많은 테스트 사례입니다 (출력에 입력).
{"regular string", "regular string"},
{"<a href=\"link\">A link</a>", "A link"},
{"<script src=\"http://evil.url.com\"/>", ""},
{"<script>", ""},
{"&lt;script&gt;", "lt;scriptgt;"}, // best effort
{"\" ' > < \n \\ é å à ü and & preserved", "\" ' > < \n \\ é å à ü and & preserved"}
더 나은 방법을 찾으면 알려주십시오.
&lt;script&gt;alert('Evil script executed');&lt;/script&gt;
합니다. 동일합니다 &
. JSoup은 변환하지 않습니다. JSoup이 입력을 정리 한 후 <script> into <script>
호출하기 때문 StringEscapeUtils.unescapeHtml
입니다.
Android에서는 다음을 시도하십시오.
String result = Html.fromHtml(html).toString();
HTML 이스 케이 핑은 실제로 제대로하기가 어렵습니다. 라이브러리 코드를 사용하여 생각하는 것보다 훨씬 미묘하기 때문에 라이브러리 코드를 사용하는 것이 좋습니다. Java에서 이것을 처리하기위한 아주 좋은 라이브러리는 Apache의 StringEscapeUtils 를 확인하십시오 .
이 작동합니다-
이것을 사용하십시오
text.replaceAll('<.*?>' , " ") -> This will replace all the html tags with a space.
이
text.replaceAll('&.*?;' , "")-> this will replace all the tags which starts with "&" and ends with ";" like , &, > etc.
Tim이 제안한 것처럼 HTML을 읽기 어려운 엉망으로 만들지 않도록 HTML을 제거하기 전에 줄 바꿈을 사용 <br/>
하여 </p>
태그 를 바꾸고 싶을 수 있습니다 .
HTML 태그를 제거 할 수 있지만 꺾쇠 괄호 사이에 HTML이 아닌 상태를 유지하는 유일한 방법 은 HTML 태그 목록을 확인하는 것 입니다. 이 라인을 따라 뭔가 ...
replaceAll("\\<[\s]*tag[^>]*>","")
그런 다음과 같은 특수 문자를 HTML로 디코딩 &
합니다. 결과는 위생적인 것으로 간주되어서는 안됩니다.
또는 HtmlCleaner 를 사용할 수 있습니다 .
private CharSequence removeHtmlFrom(String html) {
return new HtmlCleaner().clean(html).getText();
}
내가 표시 한 테스트 사례에서 허용 된 답변이 작동하지 않았습니다. "a <b 또는 b> c"의 결과는 "ab 또는 b> c"입니다.
그래서 대신 TagSoup을 사용했습니다. 내 테스트 케이스 (및 다른 몇 가지)에서 효과가있는 샷이 있습니다.
import java.io.IOException;
import java.io.StringReader;
import java.util.logging.Logger;
import org.ccil.cowan.tagsoup.Parser;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.InputSource;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
/**
* Take HTML and give back the text part while dropping the HTML tags.
*
* There is some risk that using TagSoup means we'll permute non-HTML text.
* However, it seems to work the best so far in test cases.
*
* @author dan
* @see <a href="http://home.ccil.org/~cowan/XML/tagsoup/">TagSoup</a>
*/
public class Html2Text2 implements ContentHandler {
private StringBuffer sb;
public Html2Text2() {
}
public void parse(String str) throws IOException, SAXException {
XMLReader reader = new Parser();
reader.setContentHandler(this);
sb = new StringBuffer();
reader.parse(new InputSource(new StringReader(str)));
}
public String getText() {
return sb.toString();
}
@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
for (int idx = 0; idx < length; idx++) {
sb.append(ch[idx+start]);
}
}
@Override
public void ignorableWhitespace(char[] ch, int start, int length)
throws SAXException {
sb.append(ch);
}
// The methods below do not contribute to the text
@Override
public void endDocument() throws SAXException {
}
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
}
@Override
public void endPrefixMapping(String prefix) throws SAXException {
}
@Override
public void processingInstruction(String target, String data)
throws SAXException {
}
@Override
public void setDocumentLocator(Locator locator) {
}
@Override
public void skippedEntity(String name) throws SAXException {
}
@Override
public void startDocument() throws SAXException {
}
@Override
public void startElement(String uri, String localName, String qName,
Attributes atts) throws SAXException {
}
@Override
public void startPrefixMapping(String prefix, String uri)
throws SAXException {
}
}
다음은 나누기 및 목록의 일부 서식을 처리하기위한 약간 더 많은 업데이트입니다. 나는 Amaya의 출력을 가이드로 사용했습니다.
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.util.Stack;
import java.util.logging.Logger;
import javax.swing.text.MutableAttributeSet;
import javax.swing.text.html.HTML;
import javax.swing.text.html.HTMLEditorKit;
import javax.swing.text.html.parser.ParserDelegator;
public class HTML2Text extends HTMLEditorKit.ParserCallback {
private static final Logger log = Logger
.getLogger(Logger.GLOBAL_LOGGER_NAME);
private StringBuffer stringBuffer;
private Stack<IndexType> indentStack;
public static class IndexType {
public String type;
public int counter; // used for ordered lists
public IndexType(String type) {
this.type = type;
counter = 0;
}
}
public HTML2Text() {
stringBuffer = new StringBuffer();
indentStack = new Stack<IndexType>();
}
public static String convert(String html) {
HTML2Text parser = new HTML2Text();
Reader in = new StringReader(html);
try {
// the HTML to convert
parser.parse(in);
} catch (Exception e) {
log.severe(e.getMessage());
} finally {
try {
in.close();
} catch (IOException ioe) {
// this should never happen
}
}
return parser.getText();
}
public void parse(Reader in) throws IOException {
ParserDelegator delegator = new ParserDelegator();
// the third parameter is TRUE to ignore charset directive
delegator.parse(in, this, Boolean.TRUE);
}
public void handleStartTag(HTML.Tag t, MutableAttributeSet a, int pos) {
log.info("StartTag:" + t.toString());
if (t.toString().equals("p")) {
if (stringBuffer.length() > 0
&& !stringBuffer.substring(stringBuffer.length() - 1)
.equals("\n")) {
newLine();
}
newLine();
} else if (t.toString().equals("ol")) {
indentStack.push(new IndexType("ol"));
newLine();
} else if (t.toString().equals("ul")) {
indentStack.push(new IndexType("ul"));
newLine();
} else if (t.toString().equals("li")) {
IndexType parent = indentStack.peek();
if (parent.type.equals("ol")) {
String numberString = "" + (++parent.counter) + ".";
stringBuffer.append(numberString);
for (int i = 0; i < (4 - numberString.length()); i++) {
stringBuffer.append(" ");
}
} else {
stringBuffer.append("* ");
}
indentStack.push(new IndexType("li"));
} else if (t.toString().equals("dl")) {
newLine();
} else if (t.toString().equals("dt")) {
newLine();
} else if (t.toString().equals("dd")) {
indentStack.push(new IndexType("dd"));
newLine();
}
}
private void newLine() {
stringBuffer.append("\n");
for (int i = 0; i < indentStack.size(); i++) {
stringBuffer.append(" ");
}
}
public void handleEndTag(HTML.Tag t, int pos) {
log.info("EndTag:" + t.toString());
if (t.toString().equals("p")) {
newLine();
} else if (t.toString().equals("ol")) {
indentStack.pop();
;
newLine();
} else if (t.toString().equals("ul")) {
indentStack.pop();
;
newLine();
} else if (t.toString().equals("li")) {
indentStack.pop();
;
newLine();
} else if (t.toString().equals("dd")) {
indentStack.pop();
;
}
}
public void handleSimpleTag(HTML.Tag t, MutableAttributeSet a, int pos) {
log.info("SimpleTag:" + t.toString());
if (t.toString().equals("br")) {
newLine();
}
}
public void handleText(char[] text, int pos) {
log.info("Text:" + new String(text));
stringBuffer.append(text);
}
public String getText() {
return stringBuffer.toString();
}
public static void main(String args[]) {
String html = "<html><body><p>paragraph at start</p>hello<br />What is happening?<p>this is a<br />mutiline paragraph</p><ol> <li>This</li> <li>is</li> <li>an</li> <li>ordered</li> <li>list <p>with</p> <ul> <li>another</li> <li>list <dl> <dt>This</dt> <dt>is</dt> <dd>sdasd</dd> <dd>sdasda</dd> <dd>asda <p>aasdas</p> </dd> <dd>sdada</dd> <dt>fsdfsdfsd</dt> </dl> <dl> <dt>vbcvcvbcvb</dt> <dt>cvbcvbc</dt> <dd>vbcbcvbcvb</dd> <dt>cvbcv</dt> <dt></dt> </dl> <dl> <dt></dt> </dl></li> <li>cool</li> </ul> <p>stuff</p> </li> <li>cool</li></ol><p></p></body></html>";
System.out.println(convert(html));
}
}
사용하다 Html.fromHtml
HTML 태그는
<a href=”…”> <b>, <big>, <blockquote>, <br>, <cite>, <dfn>
<div align=”…”>, <em>, <font size=”…” color=”…” face=”…”>
<h1>, <h2>, <h3>, <h4>, <h5>, <h6>
<i>, <p>, <small>
<strike>, <strong>, <sub>, <sup>, <tt>, <u>
당으로 안드로이드의 공식 자료 문서 의 모든 태그를 HTML은 일반적인 교체로 표시됩니다 문자열 프로그램이 다음을 통해 가서 실제와 대체 할 수있는 문자열 .
Html.formHtml
메소드는 Html.TagHandler
구문 분석 할 텍스트뿐만 아니라 인수로 Html.ImageGetter를 사용합니다.
String Str_Html=" <p>This is about me text that the user can put into their profile</p> ";
그때
Your_TextView_Obj.setText(Html.fromHtml(Str_Html).toString());
산출
이것은 사용자가 자신의 프로필에 넣을 수있는 텍스트입니다.
다음은 all을 대체하는 방법의 또 다른 변형입니다 (HTML 내용 | HTML 엔티티 | HTML 내용의 빈 공간)
content.replaceAll("(<.*?>)|(&.*?;)|([ ]{2,})", "");
여기서 content는 문자열입니다.
당신은 단순히 안드로이드의 기본 HTML 필터를 사용할 수 있습니다
public String htmlToStringFilter(String textToFilter){
return Html.fromHtml(textToFilter).toString();
}
위의 메소드는 입력에 대한 HTML 필터링 문자열을 반환합니다.
HTML에서 일반 텍스트로 가고 싶은 것 같습니다.
이 경우 www.htmlparser.org를 참조하십시오. 다음은 URL에서 찾은 html 파일에서 모든 태그를 제거하는 예입니다. org.htmlparser.beans.StringBean
을 사용 합니다.
static public String getUrlContentsAsText(String url) {
String content = "";
StringBean stringBean = new StringBean();
stringBean.setURL(url);
content = stringBean.getStrings();
return content;
}
다른 방법은 다음과 같습니다.
public static String removeHTML(String input) {
int i = 0;
String[] str = input.split("");
String s = "";
boolean inTag = false;
for (i = input.indexOf("<"); i < input.indexOf(">"); i++) {
inTag = true;
}
if (!inTag) {
for (i = 0; i < str.length; i++) {
s = s + str[i];
}
}
return s;
}
이 목적으로 Apache Tika 를 사용할 수도 있습니다 . 기본적으로 제거 된 HTML의 공백을 유지하며 특정 상황에서 필요할 수 있습니다.
InputStream htmlInputStream = ..
HtmlParser htmlParser = new HtmlParser();
HtmlContentHandler htmlContentHandler = new HtmlContentHandler();
htmlParser.parse(htmlInputStream, htmlContentHandler, new Metadata())
System.out.println(htmlContentHandler.getBodyText().trim())
Parse.parse(InputStream, ContentHandler, Metadata, ParseContext)
.
JSoup으로 줄 바꿈 정보를 유지하는 한 가지 방법은 모든 줄 바꿈 앞에 더미 문자열을 붙이고 JSoup을 실행하고 더미 문자열을 "\ n"으로 바꾸는 것입니다.
String html = "<p>Line one</p><p>Line two</p>Line three<br/>etc.";
String NEW_LINE_MARK = "NEWLINESTART1234567890NEWLINEEND";
for (String tag: new String[]{"</p>","<br/>","</h1>","</h2>","</h3>","</h4>","</h5>","</h6>","</li>"}) {
html = html.replace(tag, NEW_LINE_MARK+tag);
}
String text = Jsoup.parse(html).text();
text = text.replace(NEW_LINE_MARK + " ", "\n\n");
text = text.replace(NEW_LINE_MARK, "\n\n");
classeString.replaceAll("\\<(/?[^\\>]+)\\>", "\\ ").replaceAll("\\s+", " ").trim()
형식화 된 일반 HTML 텍스트 를 얻으려면 다음을 수행하십시오.
String BR_ESCAPED = "<br/>";
Element el=Jsoup.parse(html).select("body");
el.select("br").append(BR_ESCAPED);
el.select("p").append(BR_ESCAPED+BR_ESCAPED);
el.select("h1").append(BR_ESCAPED+BR_ESCAPED);
el.select("h2").append(BR_ESCAPED+BR_ESCAPED);
el.select("h3").append(BR_ESCAPED+BR_ESCAPED);
el.select("h4").append(BR_ESCAPED+BR_ESCAPED);
el.select("h5").append(BR_ESCAPED+BR_ESCAPED);
String nodeValue=el.text();
nodeValue=nodeValue.replaceAll(BR_ESCAPED, "<br/>");
nodeValue=nodeValue.replaceAll("(\\s*<br[^>]*>){3,}", "<br/><br/>");
하려면 일반 텍스트 formateed \ n으로 변경 <BR/>을에 의해 마지막 줄을 변경 :
nodeValue=nodeValue.replaceAll("(\\s*\n){3,}", "<br/><br/>");
여러 개의 replaceAll ()을 사용하여 메소드를 만들 수 있습니다.
String RemoveTag(String html){
html = html.replaceAll("\\<.*?>","")
html = html.replaceAll(" ","");
html = html.replaceAll("&"."");
----------
----------
return html;
}
가장 일반적인 대체품에 대해서는이 링크를 사용하십시오. http://tunes.org/wiki/html_20special_20characters_20and_20symbols.html
간단하지만 효과적입니다. 이 방법을 먼저 사용하여 정크를 제거하지만 첫 번째 줄은 바꾸지 않습니다. 즉 replaceAll ( "\ <. *?>", ""), 나중에 특정 키워드를 사용하여 색인을 검색 한 다음 .substring (start, end ) 불필요한 것을 제거하는 방법. 이것이 더 강력하고 전체 HTML 페이지에서 필요한 것을 정확하게 지정할 수 있습니다.
문자열에서 HTML 태그를 제거하십시오. 어딘가에 우리는 서버에서 Httpresponse와 같은 일부 응답으로받은 문자열을 구문 분석해야합니다.
따라서 구문 분석해야합니다.
다음은 문자열에서 html 태그를 제거하는 방법을 보여줍니다.
// sample text with tags
string str = "<html><head>sdfkashf sdf</head><body>sdfasdf</body></html>";
// regex which match tags
System.Text.RegularExpressions.Regex rx = new System.Text.RegularExpressions.Regex("<[^>]*>");
// replace all matches with empty strin
str = rx.Replace(str, "");
//now str contains string without html tags
new System.Text.RegularExpressions.Regex();
셨나요?