Предотвращение повторного кодирования амперсандов с помощью метода Node setTextContent

Задний план

Преобразование прямых кавычек в изогнутые кавычки и апострофы в документе XHTML. При наличии документа с прямыми кавычками (" и ') выполняется некоторая предварительная обработка для преобразования прямых кавычек в их изогнутые семантические эквиваленты (“, ”, ‘, ’ и '). Обычно свернутый символ используется для закрытия одинарных кавычек (’) и апострофов ('), но при этом теряется семантическое значение, которое я хотел бы сохранить. вместо этого используется объект --- для последующего перевода в TeX (например, \quote{outer \quote{we’re inside quotes} outer}). Таким образом:

Markdown -> XHTML (straight) -> XHTML (curled) -> TeX

Код использует встроенные в Java классы объектной модели документов (DOM).

Проблема

Вызов Node >setTextContent будет дважды кодировать любой амперсанд, что приведет к следующему результату:

“I reckon, I'm 'bout dat.”
“Elizabeth Davenport;” she said ‘Elizabeth’ to be dignified, “and really my father owns the place.”

Скорее, чем:

“I reckon, I'm 'bout dat.”
“Elizabeth Davenport;” she said ‘Elizabeth’ to be dignified, “and really my father owns the place.”

Отключение и включение путем установки инструкции обработки, похоже, не сработало.

Код

Вот код для walk дерева:

  public static void walk(
    final Document document, final String xpath,
    final Consumer<Node> consumer ) {
    assert document != null;
    assert consumer != null;

    try {
      final var expr = lookupXPathExpression( xpath );
      final var nodes = (NodeList) expr.evaluate( document, NODESET );

      if( nodes != null ) {
        for( int i = 0, len = nodes.getLength(); i < len; i++ ) {
          consumer.accept( nodes.item( i ) );
        }
      }
    } catch( final Exception ex ) {
      clue( ex );
    }
  }

Вот код, который заменяет кавычки закрученными эквивалентами:

walk(
  xhtml,
  "//*[normalize-space( text() ) != '']",
  node -> node.setTextContent( sConverter.apply( node.getTextContent() ) )
);

Где xhtml — это кавычки Document и sConverter завитков.

Вопрос

Как бы вы проинструктировали DOM принимать &apos; и друзей без повторного кодирования амперсанда?

Связанный

Полусвязанные вопросы:


person Dave Jarvis    schedule 28.06.2021    source источник


Ответы (2)


Измените предварительную обработку, чтобы заменить прямые кавычки символами Unicode, а не недопустимыми объектами XML. Эти объекты определяются HTML и не являются допустимым XML.

  • &ldquo; должно быть или \u201C, если написано как литерал Java
  • &rdquo; должно быть или \u201D, если написано как литерал Java
  • &lsquo; должно быть или \u2018, если написано как литерал Java
  • &rsquo; должно быть или \u2019, если написано как литерал Java
  • &apos; должно быть '
person Andreas    schedule 28.06.2021
comment
Это была и моя первая мысль, но я полагаю, что он хочет придать некое семантическое значение \u2019; то есть иногда он представляет собой начало вложенной цитаты, а иногда просто апостроф. - person VGR; 28.06.2021
comment
Я имел в виду конец вложенной цитаты. - person VGR; 28.06.2021
comment
U+2019 предпочтительнее для апострофа. «U+2019 ПРАВАЯ ОДИНАРНАЯ КАВАТА предпочтительнее, если символ должен представлять знак препинания, как в «Мы уже были здесь раньше». В последнем случае U+2019 также называется пунктуационным апострофом». (Однако стандарт можно было бы улучшить, определив два отдельных символа.) - person Dave Jarvis; 29.06.2021
comment
@DaveJarvis Извините, я не вижу смысла в этом комментарии. Если вы хотите использовать aka \u2019 aka правую одинарную кавычку, сделайте это. Апостроф ' или \u0027. - person Andreas; 29.06.2021
comment
Утверждение &apos; should be ' немного вводит в заблуждение, поскольку, согласно спецификации Unicode, ' не является предпочтительным символом. Скорее это U+2019. Следовательно, если бы символ замены был закодирован в соответствии со спецификацией, было бы довольно сложно устранить неоднозначность на стороне TeX. - person Dave Jarvis; 29.06.2021
comment
@DaveJarvis И XML 1.0, и HTML 5 определяют объект &apos; как ' он же U+0027. В этом нет ничего предпочтительного, это определение. Если документ XHTML содержит &apos;, синтаксический анализатор XML должен проанализировать его как ', если не отключено расширение ссылок на объекты. - person Andreas; 29.06.2021
comment
Я отказался от попыток дразнить &apos; и отказался от идеи позволить TeX оборачивать символы в \quote{...}. Это действительно отстой, что \u2019 используется как для закругленных закрывающих кавычек , так и для загнутых апострофов. - person Dave Jarvis; 29.06.2021
comment
@DaveJarvis Согласен. Это разные персонажи, концептуально, с очень разными значениями. Обычно Unicode хорошо справляется с такими различиями… - person VGR; 30.06.2021

XML-процессоры могут свободно рассматривать символы и символьные сущности как взаимозаменяемые, поэтому попытка использовать символьные сущности для указания семантического значения обречена на провал.

Вместо этого я бы использовал разметку. Я подозреваю, что пользовательские инструкции по обработке были бы хорошим способом «незаметно» добавить семантическое значение:

<text>"She told me, 'Don't forget the bread.'"</text>

превратится в:

<text><?q?>“She told me, <?q?>‘Don’t forget the bread.<?q?>’<?q?>”</text>

Где инструкция обработки <?q?> является сигналом того, что следующая кодовая точка имеет семантическое значение как кавычка.

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

<text><?quote-start?>“She told me, <?quote-start?>‘Don't forget the bread.<?quote-end?>’<?quote-end?>”</text>

Как бы там ни было, XHTML определяет собственный <quote> element для обработки именно этого случая.

(Обычный HTML содержит элемент <q> который семантически похож, но также указывает браузерам автоматически отображать кавычки, что означает, что HTML-документ, который использует <q>, не должен включать собственные кавычки.)

person VGR    schedule 28.06.2021
comment
К сожалению, это потребовало бы больше усилий со стороны TeX, которая уже была разработана для разбора сущностей. Хотя это хорошая идея. - person Dave Jarvis; 29.06.2021