Запретить Jsoup отбрасывать лишние пробелы

Я использую Jsoup для дезинфекции пользовательского ввода из формы. Рассматриваемая форма содержит <textarea>, который ожидает обычный текст. Когда форма отправлена, я очищаю ввод с помощью Jsoup.clean(textareaContents); однако, поскольку html игнорирует лишние пробелы, Jsoup.clean() удалит из ввода ценные пробельные символы.

Например, если кто-то ввел несколько строк текста в поле textarea:

hello

test

после Jsoup.clean() у вас будет:

hello test

Как заставить Jsoup.clean() сохранять пробелы? Я знаю, что он предназначен для синтаксического анализа html, а это не html, так что есть ли лучшая альтернатива?


person Keith    schedule 28.03.2011    source источник


Ответы (3)


Если ваша текстовая область просто ожидает простой текст, то я думаю, вам лучше просто HTML избегать простого текста. т.е. преобразовать введенные пользователем теги < и > в &lt; и &gt; соответственно. Либо на входе наш выход (ввод может быть безопаснее, поэтому вам нужно подумать об этом только один раз).

очиститель jsoup HTML, как вы говорите, предназначен для анализа ненадежного входного HTML и выводить доверенный HTML, где форматирование выполняется с помощью элементов.

person Jonathan Hedley    schedule 29.04.2011

Для будущих поколений, если вам все еще нужен доступ к исходному тексту с пробелами, вы можете использовать TextNode.getWholeText() метод.

Образец кода:

/**
 * @param cell element that contains whitespace formatting
 * @return
 */
public static String getText(Element cell) {
    String text = null;
    List<Node> childNodes = cell.childNodes();
    if (childNodes.size() > 0) {
        Node childNode = childNodes.get(0);
        if (childNode instanceof TextNode) {
            text = ((TextNode)childNode).getWholeText();
        }
    }
    if (text == null) {
        text = cell.text();
    }
    return text;
}

В приведенном выше коде мы предполагаем, что переданный элемент содержит текстовое содержимое непосредственно внутри тела элемента (мы берем первый узел). Если это не так, он вернется к обычному Element.text()< /а> метод.

person Neeme Praks    schedule 29.12.2011

Ответ Neeme Praks был очень хорошим и правильно сохранил пробелы. Однако встроенный HTML действительно все портит.

<span>This is<br />some text.  Cool story.</span>

Результаты в

"This is"

Или, если вы передаете элемент, у которого нет собственного текста, он возвращает null.

Поэтому мне пришлось немного переработать метод для своих целей. Это может помочь некоторым людям, поэтому я публикую это здесь. Основная идея состоит в том, чтобы повторять дочерние элементы, а не просто брать первый. Это также включает случай захвата HTML для любых элементов без дочерних элементов.

Таким образом, исходный фрагмент возвращается:

This is<br />some text.  Cool story.

public static String getText(Element cell) {
    StringBuilder textBuilder = new StringBuilder();
    for (Node node : cell.childNodes()) {
        if (node instanceof TextNode) {
            textBuilder.append(((TextNode)node).getWholeText());
        }
        else {
            for (Node childNode : node.childNodes()) {
                textBuilder.append(getText((Element)childNode));
            }
            textBuilder.append(node.outerHtml());
        }
    }
    if (cell.childNodes().isEmpty()) {
        textBuilder.append(cell.outerHtml());
    }
    return textBuilder.toString();
}
person Sloloem    schedule 25.01.2016
comment
У меня есть такой же необычный вариант использования, когда пробелы имеют значение, а текст приправлен тегами <br>. Я добавил ваш метод, и теперь все хорошо (после нескольких часов, потраченных на это за последние два дня). Спасибо, что нашли время опубликовать свой метод. - person Paul; 11.01.2017
comment
почему у вас есть textBuilder.append(node.outerHtml());? Это приведет к дублированию содержимого тега. т.е. ‹b›‹i›hello›‹/i›‹/b› станет hello‹i›hello‹/i›. Я что-то упускаю? - person Ammar; 02.08.2017