提问人:ScottD 提问时间:9/29/2023 更新时间:9/30/2023 访问量:69
如何在一些非常糟糕的xhtml中替换<>字符
How can I replace <> chars in some really bad xhtml
问:
我正在将 xhtml 文档处理成 TEI。xhtml 文档最初是旧的 .doc 文件。创建文档文件的人使用<>字符来指示何时将字母、单词或单词添加到原始文档中。下面是文档的片段。
<p>
<X> presented <<strike>it</strike>>
to others <X> in the form of a babe, [ERASED] X [END ERASE] <at
first — and according to their belief her> <strike>her
mental conception and</strike>
<strike>they called her</strike>
spiritual conception <of man <brought forth> a material man
<and was> <strike>but</strike>
a> <strike>matter, flesh and
bones</strike> <miraculous
conception (<strike>and</strike><but>
it was n<strike>either</strike><ot>)
and> and<sup>
<a shape="rect" class="sdfootnoteanc" name="sdfootnote138anc"
href="#sdfootnote138sym">
<sup>138</sup>
</a>
</sup>
</p>
我正在使用 xsl 来处理 xhtml 和函数
<xsl:when test="matches($text, '<.+>', 's')">
只要没有任何嵌套对,它就可以工作。下面的文本是上面示例中的嵌套示例。
<of man <brought forth> a material man <and was> <strike>but</strike> a>
matches() 函数失败,因为对于第一个 <,它抓住了第一个 > 它看到的,这是第二个 < 的匹配,而不是第一个。在那之后,事情就走下坡路了。
我正在考虑使用 sed 和正则表达式来替换 &alt > 对,但我不明白这不会因为同样的原因而失败。
寻找有关如何解决此问题的好主意。
谢谢
斯科特
答:
下面说明的方法使用文本替换将角度转换为开始和结束标记。然后,它分析文档并按相反的文档顺序处理元素,以便嵌套到其他插入中的插入在外部插入之前进行处理。此处理包括 上的文本替换,以便可以一起处理元素的所有子元素,无论它们是文本节点还是其他元素。<>
ins
<ins>
innerHTML
<ins>
使用哪种文本替换取决于要实现的目标。在此示例中,插入被转换为带有边框的元素,以便可以看到嵌套的效果。<span>
var p = document.querySelector("p");
var doc = new DOMParser().parseFromString(p.innerHTML
.replace(/</g, "<ins>")
.replace(/>/g, "</ins>"), "text/html");
var nodes = [];
for (var node, iter = doc.evaluate("//ins", doc.body, undefined, XPathResult.ORDERED_NODE_ITERATOR_TYPE);
(node = iter.iterateNext());)
nodes.unshift(node);
for (node of nodes)
/* The next statement would destroy any nested <ins> nodes,
but we have already processed them before. */
node.outerHTML = '<span>' + node.innerHTML + '</span>';
p.innerHTML = doc.body.innerHTML;
span {
display: inline-block;
border: 1px solid black;
margin: 1px;
}
<p>
<X> presented <<strike>it</strike>> to others <X> in the form of a babe, [ERASED] X [END ERASE] <at first — and according to their belief her> <strike>her
mental conception and</strike>
<strike>they called her</strike> spiritual conception <of man <brought forth> a material man <and was> <strike>but</strike> a> <strike>matter, flesh and
bones</strike> <miraculous conception (<strike>and</strike><but> it was n<strike>either</strike><ot>) and> and<sup>
<a shape="rect" class="sdfootnoteanc" name="sdfootnote138anc"
href="#sdfootnote138sym">
<sup>138</sup>
</a>
</sup>
</p>
上面的处理是使用 Javascript 的 document.evaluate
方法完成的。
仅具有 XSLT 处理器和文本操作的解决方案可能如下所示:
- 在输入文件中,使用 sed 等工具替换 和 with。
<
<ins>
>
</ins>
- 使用以下 XSL 转换转换输入文件(使用这些替换项)。同样,模板必须根据您想要实现的目标进行调整。
match="ins"
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="ins">
<span style="display: inline-block; border: 1px solid black; margin: 1px;">
<xsl:apply-templates/>
</span>
</xsl:template>
</xsl:stylesheet>
评论
请注意,除了 Heiko 的回答之外,如果您使用支持 XSLT 3 的当前版本的 Saxon,则可以从命名模板(作为命令选项)(而不是 source 选项)开始,在读取文件后执行正则表达式字符串操作,然后根据需要使用 or 解析标记,并通过模板推送它, 如需进一步处理:-it
xsl:initial-template
-s
unparsed-text
parse-xml
parse-xml-fragment
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="3.0"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="#all">
<xsl:param name="input-html" as="xs:string">sample1.html</xsl:param>
<xsl:param name="regex1" as="xs:string">&lt;</xsl:param>
<xsl:param name="regex2" as="xs:string">&gt;</xsl:param>
<xsl:param name="element-name" as="xs:string" static="yes" select="'ins'"/>
<xsl:param name="start-tag" as="xs:string" select="'<' || $element-name || '>'"/>
<xsl:param name="end-tag" as="xs:string" select="'</' || $element-name || '>'"/>
<xsl:variable name="replaced-html" select="$input-html => unparsed-text() => replace($regex1, $start-tag) => replace($regex2, $end-tag) => parse-xml-fragment()"/>
<xsl:mode on-no-match="shallow-copy"/>
<xsl:template name="xsl:initial-template">
<xsl:apply-templates select="$replaced-html"/>
</xsl:template>
<xsl:template _match="{$element-name}">
<span>
<xsl:apply-templates/>
</span>
</xsl:template>
</xsl:stylesheet>
评论