2015-08-03 19 views
9

İki <script type="application/javascript">/* .. */</script> öğeyi içeren bir JSoup Belgesi oluşturuyorum.JS dahil bir JSoup Belgesi nasıl oluşturulur?

Sorun: .html() veya .toString() numaralı telefonu aradığımda JSoup JavaScript'imden ayrılır.

if (foo && bar) 

if (foo &amp;&amp; bar) 

o JSoup kaçarken <script> Element görmezden yapılandırmak mümkün mü alır ??


Bu, (temelde) jsoup belgesini nasıl oluşturduğumdur.

final Document doc = Document.createShell(""); 
final Element head = doc.head(); 
head.appendElement("meta").attr("charset", "utf-8"); 
final String myJS = ...; 
head.appendElement("script").attr("type", "application/javascript").text(myJS); 

Benim şu anki geçici çözüm .html() üzerinde String.replace bir yer tutucu değiştirmektir. Ama bu bir çeşit hacky.

+0

cevabımı güncelledik:

Bu kullandığım budur. – alkis

cevap

-1

Bunu "devre dışı bırakamaz". "Yapamaz" ile kolayca demek istemiyorum. Çok fazla düşündüğüm düğüm geçişini engellemek/yeniden uygulamak zorundasınız. Bu

String dom = Parser.unescapeEntities(doc.html(), false); 

Güncelle biz sorunun yerini tespit etmek zorunda hepsinden

İlk yapabilirsiniz.

TextNode.java

void outerHtmlHead(StringBuilder accum, int depth, 
     Document.OutputSettings out) { 
    if ((out.prettyPrint()) 
      && ((((siblingIndex() == 0) 
        && (this.parentNode instanceof Element) 
        && (((Element) this.parentNode).tag().formatAsBlock()) && (!(isBlank()))) || ((out 
        .outline()) && (siblingNodes().size() > 0) && (!(isBlank())))))) { 
     indent(accum, depth, out); 
    } 

    boolean normaliseWhite = (out.prettyPrint()) 
      && (parent() instanceof Element) 
      && (!(Element.preserveWhitespace(parent()))); 
    Entities.escape(accum, getWholeText(), out, false, normaliseWhite, 
      false); 
} 
Özellikle sorun burada

Entities.escape(accum, getWholeText(), out, false, normaliseWhite,false); 

Entities.java

static void escape(StringBuilder accum, String string, 
     Document.OutputSettings out, boolean inAttribute, 
     boolean normaliseWhite, boolean stripLeadingWhite) { 
    boolean lastWasWhite = false; 
    boolean reachedNonWhite = false; 
    EscapeMode escapeMode = out.escapeMode(); 
    CharsetEncoder encoder = out.encoder(); 
    CoreCharset coreCharset = CoreCharset.access$300(encoder.charset() 
      .name()); 
    Map map = escapeMode.getMap(); 
    int length = string.length(); 
    int codePoint; 
    for (int offset = 0; offset < length; offset += Character 
      .charCount(codePoint)) { 
     codePoint = string.codePointAt(offset); 

     if (normaliseWhite) { 
      if (StringUtil.isWhitespace(codePoint)) { 
       if ((stripLeadingWhite) && (!(reachedNonWhite))) 
        continue; 
       if (lastWasWhite) 
        continue; 
       accum.append(' '); 
       lastWasWhite = true; 
       continue; 
      } 
      lastWasWhite = false; 
      reachedNonWhite = true; 
     } 

     if (codePoint < 65536) { 
      char c = (char) codePoint; 

      switch (c) { 
      case '&': 
       accum.append("&amp;"); 
       break; 
      case ' ': 
       if (escapeMode != EscapeMode.xhtml) 
        accum.append("&nbsp;"); 
       else 
        accum.append("&#xa0;"); 
       break; 
      case '<': 
       if ((!(inAttribute)) || (escapeMode == EscapeMode.xhtml)) 
        accum.append("&lt;"); 
       else 
        accum.append(c); 
       break; 
      case '>': 
       if (!(inAttribute)) 
        accum.append("&gt;"); 
       else 
        accum.append(c); 
       break; 
      case '"': 
       if (inAttribute) 
        accum.append("&quot;"); 
       else 
        accum.append(c); 
       break; 
      default: 
       if (canEncode(coreCharset, c, encoder)) 
        accum.append(c); 
       else if (map.containsKey(Character.valueOf(c))) 
        accum.append('&') 
          .append((String) map.get(Character.valueOf(c))) 
          .append(';'); 
       else 
        accum.append("&#x") 
          .append(Integer.toHexString(codePoint)) 
          .append(';'); 
      } 
     } else { 
      String c = new String(Character.toChars(codePoint)); 
      if (encoder.canEncode(c)) 
       accum.append(c); 
      else 
       accum.append("&#x").append(Integer.toHexString(codePoint)) 
         .append(';'); 
     } 
    } 
} 
Tamam şimdi sorun tespit ettik

olduğunu yani ne çözüm. İşte sorun bu. Normalde ne yapacağını html() veya toString()-calls outerHtml veya outerHtml() çağrılırken her düğüm için denir (outerHtmlHead geçersiz olacaktır. Sorun bu yöntem package private yüzden paketin dışına iptal etmek üzere, görünür değil olmasıdır.

kolay bir yolu Jsoup kaynak kodunu indirip aynı paket içerisinde özel sınıf dahil olacaktır. Başka korunan bu iki görünürlüğünü değiştirme konusunda olacaktır.

abstract void outerHtmlHead(StringBuilder paramStringBuilder, int paramInt, Document.OutputSettings paramOutputSettings); 

abstract void outerHtmlTail(StringBuilder paramStringBuilder, int paramInt,Document.OutputSettings paramOutputSettings); 

proje içinde derleme hataları olacaktır th azaltmak mümkün değil yaklaşık class Node uzanır her sınıf geçersiz kılınan bir yöntemin görünürlüğü. Görünürlüğü de protected olarak değiştirin. Bundan sonra TextNode sınıfını genişleten yeni bir sınıf uygulayabilirsiniz., Açıkça metni belirtmek gerek Böyle bir şey ben

public class RawTextNode extends TextNode { 

    @Override 
    protected void outerHtmlHead(StringBuilder accum, int depth, OutputSettings out) { 
     if ((out.prettyPrint()) 
       && ((((siblingIndex() == 0) 
         && (parentNode() instanceof Element) 
         && (((Element) parentNode()).tag().formatAsBlock()) && (!(isBlank()))) || ((out 
         .outline()) && (siblingNodes().size() > 0) && (!(isBlank())))))) { 
      indent(accum, depth, out); 
     } 
    } 
} 

inanmak yeterli olacaktır ve kod buna göre
head.appendElement("script").attr("type", "application/javascript").appendChild(new RawTextNode(myJS, "")); 

olduğu gibi bunu bırakırsanız

, metin TextNode tarafından temsil edilecek değiştirmeli özel sınıfınız tarafından temsil edilmelidir.

Elbette daha derine gidebilir ve genel bir şekilde script parçalarını işleyen yeni bir sınıf oluşturabilirsiniz.

+0

Ama bu benim gerçek HTML'mden de kaçardı, değil mi? > '' '' vb – Brettetete

+0

Doğru. Bunun bir sorun olmayacağını düşünmüştüm (her ne kadar betik bölümünün kaçması gerektiğini açıkça belirtmiş olsanız da). Benim hatam. Günün ilerleyen saatlerinde başka bir şey sağlamaya çalışacağım. – alkis

+0

Cevabımı güncelledim. Ne yazık ki çözüm oldukça zahmetli. – alkis

2

HariciHtmlHead yöntemi artık geçersiz kılınamaz.

head 
    .appendElement("script") 
    .attr("type","text/javascript") 
    .appendChild(new DataNode(getJavaScript(),"")); 
+0

Bu benim için gerçekten işe yarayan şeydi! :) Teşekkür ederim! – joaomgcd

İlgili konular