如何解决使用 xsl:accumulator 跟踪两个 PI 之间的文本节点
我正在学习 XSLT 3.0 中的累加器,但我没有找到任何可以帮助我解决当前问题的示例。我有大文件,其中使用处理指令来标记修改。我需要将这些处理成可见的标记以供审查过程。使用累加器,我成功地跟踪了要显示的最新修改代码。到目前为止,一切都很好。
由于原始文件很大,我创建了一个简单的示例输入 XML,它显示了我的任务的本质,并且我调整了我的 XSL 以显示我正在尝试使用累加器。
简单的输入文件:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<div>
<p>Paragraph 1</p>
<?MyPI Start Modification 1?>
<p>Paragraph 2</p>
<p>Paragraph 3</p>
<?MyPI End Modification 1?>
</div>
<div>
<list>
<item>
<p>Paragraph 4</p>
<?MyPI Start Modification 1?>
<p>Paragraph 5</p>
<?MyPI End Modification 1?>
</item>
<item>
<?MyPI Start Modification 1?>
<p>Paragraph 6</p>
<p>Paragraph 7</p>
<?MyPI End Modification 1?>
<?MyPI Start Modification 2?>
<p>Paragraph 8</p>
<?MyPI End Modification 2?>
</item>
</list>
<p>Paragraph 9</p>
</div>
</root>
我的 XSL 使用累加器进行当前修改:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs"
version="3.0">
<xsl:mode use-accumulators="#all"/>
<xsl:accumulator name="modifier" initial-value="'Base text'">
<xsl:accumulator-rule match="processing-instruction('MyPI')[contains(.,'Modification')]">
<xsl:choose>
<xsl:when test="contains(.,'Start')">
<xsl:value-of select="substring-after(.,'Start ')"/>
</xsl:when>
<xsl:otherwise>Base text</xsl:otherwise>
</xsl:choose>
</xsl:accumulator-rule>
</xsl:accumulator>
<xsl:template match="/">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="node()">
<xsl:copy>
<xsl:apply-templates select="node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="processing-instruction('MyPI')">
<marker>
<xsl:value-of select="accumulator-after('modifier')"/>
</marker>
</xsl:template>
</xsl:stylesheet>
使用此 XSL 输出:
<?xml version="1.0" encoding="UTF-8"?><root>
<div>
<p>Paragraph 1</p>
<marker>Modification 1</marker>
<p>Paragraph 2</p>
<p>Paragraph 3</p>
<marker>Base text</marker>
</div>
<div>
<list>
<item>
<p>Paragraph 4</p>
<marker>Modification 1</marker>
<p>Paragraph 5</p>
<marker>Base text</marker>
</item>
<item>
<marker>Modification 1</marker>
<p>Paragraph 6</p>
<p>Paragraph 7</p>
<marker>Base text</marker>
<marker>Modification 2</marker>
<p>Paragraph 8</p>
<marker>Base text</marker>
</item>
</list>
<p>Paragraph 9</p>
</div>
</root>
我遇到的问题是,当它们之间没有文本时,应该隐藏相同修改代码的关闭和打开标记。它们可能会紧随其后(这很简单),但它们之间也有一些非文本元素边界。我试图创建一个累加器来跟踪自上次修改标记以来的所有文本,但这会导致对同一个累加器的嵌套调用,从而产生运行时错误。我正在寻找的是一种方法,该方法不断向累加器添加文本,并在找到修改 PI 时将其重置为空字符串。这是我的试用累加器导致嵌套调用过多:
<xsl:accumulator name="text" initial-value="''">
<xsl:accumulator-rule match="node()">
<xsl:choose>
<xsl:when test="self::processing-instruction('MyPI')"/>
<xsl:when test="self::text()">
<xsl:value-of select="concat(accumulator-after('text'),.)"/>
</xsl:when>
</xsl:choose>
</xsl:accumulator-rule>
</xsl:accumulator>
我想我还不明白累加器是如何工作的,这使得我很难得到我想要的结果。
上述简单 XML 所需的输出:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<div>
<marker>Base text</marker>
<p>Paragraph 1</p>
<marker>Modification 1</marker>
<p>Paragraph 2</p>
<p>Paragraph 3</p>
<marker>Base text</marker>
</div>
<div>
<list>
<item>
<p>Paragraph 4</p>
<marker>Modification 1</marker>
<p>Paragraph 5</p>
</item>
<item>
<p>Paragraph 6</p>
<p>Paragraph 7</p>
<marker>Mpdification 2</marker>
<p>Paragraph 8</p>
</item>
</list>
<marker>Base text</marker>
<p>Paragraph 9</p>
</div>
</root>
希望有人能指出我正确的方向。我猜想积累文本节点,因为 XML 处理中的特定节点将是一个需要更多人解决的问题。在我目前的情况下,我不需要实际的文本内容,我只需要知道自上次 PI 以来是否有任何可见文本(即我需要删除或忽略此检查中的任何空格)。
如果有另一种不涉及累加器的方法,那也很好。
在此先感谢您的帮助
解决方法
也许
<xsl:accumulator name="text" initial-value="()" as="xs:string?">
<xsl:accumulator-rule match="processing-instruction('MyPI')" select="''"/>
<xsl:accumulator-rule match="text()[normalize-space()]" select="$value || ."/>
</xsl:accumulator>
为您提供了一个关于如何设置累加器以收集文本节点值的示例,我不确定我是否理解将累加器重置为空字符串的条件,因此这基本上是您样本中的匹配项,只是转录在(希望)可编译的 XSLT 3 中,如果有更多与开始或结束处理指令对或名称相关的条件,您可以进行调整。
至于解释 $value
变量的规范,请参阅 https://www.w3.org/TR/xslt-30/#accumulator-declaration:
select 属性和包含的序列构造函数 xsl:accumulator-rule 元素是互斥的:如果选择 属性存在则序列构造函数必须为空。这 xsl:accumulator-rule 的 select 属性中的表达式或 包含的序列构造函数使用静态上下文进行评估,该上下文 遵循样式表中表达式的正常规则,除了:
上下文中存在一个附加变量。这个名字
变量是 value
(在没有命名空间中),它的类型是
出现在 xsl:accumulator 声明的 as 属性中。
用于评估表达式或序列的上下文项 构造函数将始终是与模式匹配的节点 匹配属性。
https://www.w3.org/TR/xslt-30/#accumulator-examples 中的两个示例也使用了 $value
。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。