使用 Node 的 setTextContent 方法防止重新编码&符号

Prevent re-encoding ampersands using Node's setTextContent method

背景

在 XHTML 文档中将直引号转换为弯引号和撇号。给定一个带有直引号的文档("'),执行一些预处理以将直引号转换为它们的卷曲语义等价物(“”‘’')。通常,卷曲字符 用于结束单引号 (’) 撇号 ('),但这会丢失 semantic 的意思,我想通过使用实体来保留它——以便随后翻译成 TeX(例如,\quote{outer \quote{we’re inside quotes} outer})。因此:

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

代码正在使用 Java 的内置文档对象模型 (DOM) 类.

问题

调用 NodesetTextContent 方法将对任何符号进行双重编码,结果为:

“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() ) )
);

其中 xhtmlDocumentsConverter 卷曲引号。

问题

你如何指示 DOM 接受 &apos; 和朋友而不重新编码符号?

相关

半相关问题:

更改预处理以将直引号替换为 Unicode 字符,而不是无效的 XML 实体。这些实体由 HTML 定义,并且无效 XML.

  • &ldquo; 应该是 \u201C 如果写成 Java literal
  • &rdquo; 应该是 \u201D 如果写成 Java literal
  • &lsquo; 应该是 \u2018 如果写成 Java literal
  • &rsquo; 应该是 \u2019 如果写成 Java literal
  • &apos; 应该是 '

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 defines its own <quote> element 来处理这个确切的案例。

(常规 HTML has a <q> element 语义相似,但它也告诉浏览器自动呈现引号,这意味着 HTML 文档使用 <q>不得包含其自身的引号。)