2014-01-07 2 views
6

Когда Jsoup сталкивается с определенными типами HTML (сложными или неправильными), он может издавать плохо сформированный HTML-код. Примером может служить:Как может Jsoup выводить хорошо сформированный XML?

<html> 
<head> 
    <meta name="x" content="y is "bad" here"> 
</head> 
<body/> 
</html> 

где цитаты должны были быть экранированы. Когда Jsoup анализирует это, он испускает:

<html> 
<head> 
    <meta name="x" content="y is " bad"="" here"="" /> 
</head> 
<body></body> 
</html> 

который не соответствует HTML или XML. Это проблематично, так как это не сработает при следующем синтаксическом анализаторе по цепочке.

Есть ли способ гарантировать, что Jsoup либо выдает сообщение об ошибке, либо (например, HtmlTidy) может выводить хорошо сформированный XML, даже если он потерял некоторую информацию (ведь мы не можем теперь точно знать, что правильно).

UPDATE: Код, который не удается это:

@Test 
public void testJsoupParseMetaBad() { 
    String s = "<html><meta name=\"x\" content=\"y is \"bad\" here\"><body></html>"; 
    Document doc = Jsoup.parse(s); 
    String ss = doc.toString(); 
     Assert.assertEquals("<html> <head> <meta name=\"x\" content=\"y is \"" 
      +" bad\"=\"\" here\"=\"\" /> </head> <body></body> </html>", ss); 
} 

Я использую:

<dependency> 
     <groupId>org.jsoup</groupId> 
     <artifactId>jsoup</artifactId> 
     <version>1.7.2</version> 
    </dependency> 

Другие, кажется, имеют те же проблемы: JSoup - Quotations inside attributes Ответ здесь не поможет мне Я должен принять то, что мне дано

+0

Поскольку jSoup является DOM-парсер это не следует делать этого. Восстановление HTML-текста из DOM не может привести к выходу (IMHO). Вы включили бы образец кода, который показывает это поведение? – Tomalak

+1

Я согласен с вашей логикой. Я добавил код, который я использую для анализа «HTML» выше. –

+0

@Tomalak Где говорится, что jSoup является парсером DOM (в смысле w3c)? Местные имена кажутся одинаковыми, но это все. После быстрого взгляда на источник, исправление этого, вероятно, требует изменения кода. –

ответ

1

Проблема заключается в том, что вы разбираете, поскольку jsoup создает 3 атрибута из:

content="y is "bad" here" 

и имя атрибута содержит символ «символ». Jsoup избегает значений для атрибутов, но не его имени.

Поскольку вы строите html-документ из строки, вы можете получить ошибку на фазе разбора. Существует метод, который получает аргумент org.jsoup.parser.Parser. Метод разбора по умолчанию - это не отслеживание ошибок.

String s = "<html><meta name=\"x\" content=\"y is \"bad\" here\"><body></html>"; 
    Parser parser = Parser.htmlParser(); // or Parser.xmlParser 
    parser.setTrackErrors(100); 
    Document doc = Jsoup.parse(s, "", parser); 
    System.out.println(parser.getErrors()); 

Выход:

[37: Неожиданный символ 'а' во входном состоянии [AfterAttributeValue_quoted], 40: Неожиданный символ '' во входном состоянии [имя_атрибута], 46: Неожиданный символ '>' на входе состояние [Имя_атрибута]]

в случае, если вы не хотите, чтобы изменить разобрана и просто хотите, чтобы получить правильный вывод, который вы могли бы просто удалить недопустимые атрибуты:

public static void fixIt(Document doc) { 
    Elements els = doc.getAllElements(); 
    for(Element el:els){ 
     Attributes attributes = el.attributes(); 
     Set<String> remove = new HashSet<>(); 
     for(Attribute a:attributes){ 
      if(isForbidden(a.getKey())){ 
       remove.add(a.getKey()); 
      } 
     } 

     for(String k:remove){ 
      el.removeAttr(k); 
     } 
    } 
} 

public static boolean isForbidden(String el) { 
    return el.contains("\""); //TODO 
} 
Смежные вопросы