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

Prevent re-encoding ampersands using Node's setTextContent method

提问人:Dave Jarvis 提问时间:6/29/2021 最后编辑:Dave Jarvis 更新时间:6/29/2021 访问量:229

问:

背景

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

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

该代码使用 Java 的内置文档对象模型 (DOM) 类。

问题

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

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

相关

半相关问题:

java dom 编码 xhtml &amp; 符号

评论


答:

1赞 Andreas 6/29/2021 #1

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

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

评论

0赞 VGR 6/29/2021
这也是我的第一个想法,但我相信他想给;意思是,有时它代表嵌套引号的开头,有时它只是一个撇号。\u2019
0赞 VGR 6/29/2021
我的意思是,表示嵌套引号的结尾。
1赞 Dave Jarvis 6/29/2021
U+2019 是撇号的首选。“U+2019 右单引号是首选,其中字符表示标点符号,如”我们以前来过这里”。在后一种情况下,U+2019 也被称为标点符号撇号。(不过,通过定义两个单独的字符,可以改进标准。
1赞 Dave Jarvis 6/30/2021
我放弃了试图梳理直通,也放弃了让 TeX 将角色包裹起来的想法。它真的很糟糕,用于卷曲的结束引号卷曲的撇号。&apos;\quote{...}\u2019
1赞 VGR 6/30/2021
@DaveJarvis同意。从概念上讲,它们是不同的字符,具有非常不同的含义。通常Unicode对这种差异很有好处......
1赞 VGR 6/29/2021 #2

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>元素来处理这种确切的情况。

(常规 HTML 有一个 <q> 元素,它在语义上相似,但它也告诉浏览器自动呈现引号,这意味着使用 HTML 的文档不得包含自己的引号。<q>

评论

0赞 Dave Jarvis 6/30/2021
不幸的是,这将在 TeX 方面付出更多的努力,因为 TeX 方面已经开发用于解析实体。不过,这是个好主意。