XSLT - 识别具有相同属性值模式的连续节点

2024-01-17

我有这样的xml,

<section>
        <p id="ss_main">aa</p>
        <p id="ss_chap">bb</p>
        <p id="main">cc</p>
        <p id="main">dd</p>
        <p id="main">ee</p>
        <p id="ss_main">ff</p>
        <p id="main">gg</p>
        <p id="main">hh</p>
        <p id="main">ii</p>
        <p id="main">jj</p>
        <p id="ss_chap">xx</p>
        <p id="ss_main">yy</p>
        <p id="ss_chap">zz</p>
    </section>

我的要求是放置名为的新节点<ss_start> and <ss_end>通过覆盖以以下开头的现有节点ss.

所以输出应该是

<section>
        <ss_start/>
        <p id="ss_main">aa</p>
        <p id="ss_chap">bb</p>
        <ss_end/>
        <p id="main">cc</p>
        <p id="main">dd</p>
        <p id="main">ee</p>
        <ss_start/>
        <p id="ss_main">ff</p>
        <ss_end/>
        <p id="main">gg</p>
        <p id="main">hh</p>
        <p id="main">ii</p>
        <p id="main">jj</p>
        <ss_start/>
        <p id="ss_chap">xx</p>
        <p id="ss_main">yy</p>
        <p id="ss_chap">zz</p>
        <ss_end/>
    </section>

我可以像下面这样编写 xsl 来覆盖特定节点<ss_start> and <ss_end>

<xsl:template match="p[@id='ss_main']">
        <ss_start/>
        <p id="ss_main"><xsl:apply-templates/></p>
        <ss_end/>
    </xsl:template>

但我正在努力寻找 id attr 从开始的连续节点ss并覆盖它们<ss_start> and <ss_end>.

谁能建议我一种方法,我该怎么做?


XSLT 1.0 同级递归

在 XSLT 1.0 中,您可以按如下方式执行此操作,它使用称为兄弟递归(尽管兄弟遍历可能是一个更好的术语)。

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="1.0">

    <xsl:output indent="yes" />

    <xsl:template match="node() | @*">
        <xsl:copy>
            <xsl:apply-templates select="node() | @*" />
        </xsl:copy>
    </xsl:template>

    <xsl:template match="section">
        <xsl:copy>
            <xsl:apply-templates select="*[1]" />
        </xsl:copy>
    </xsl:template>

    <xsl:template match="section/*[starts-with(@id, 'ss')]" priority="5">
        <xsl:if test="self::*[not(preceding-sibling::*[1][starts-with(@id, 'ss')])]">
            <ss_start />
        </xsl:if>
        <xsl:copy>
            <xsl:apply-templates select="node() | @*" />
        </xsl:copy>
        <xsl:if test="self::*[not(following-sibling::*[1][starts-with(@id, 'ss')])]">
            <ss_end />
        </xsl:if>
        <xsl:apply-templates select="following-sibling::*[1]" />
    </xsl:template>

    <xsl:template match="section/*">
        <xsl:copy>
            <xsl:apply-templates select="node() | @*" />
        </xsl:copy>
        <xsl:apply-templates select="following-sibling::*[1]" />
    </xsl:template>

</xsl:stylesheet>

当针对您的输入运行时,将创建以下输出:

<?xml version="1.0" encoding="UTF-8"?>
<section>
   <ss_start/>
   <p id="ss_main">aa</p>
   <p id="ss_chap">bb</p>
   <ss_end/>
   <p id="main">cc</p>
   <p id="main">dd</p>
   <p id="main">ee</p>
   <ss_start/>
   <p id="ss_main">ff</p>
   <ss_end/>
   <p id="main">gg</p>
   <p id="main">hh</p>
   <p id="main">ii</p>
   <p id="main">jj</p>
   <ss_start/>
   <p id="ss_chap">xx</p>
   <p id="ss_main">yy</p>
   <p id="ss_chap">zz</p>
   <ss_end/>
</section>

我现在看到您用 xslt-2.0 标记了您的问题,这意味着您可以使用分组。我将尝试使用 XSLT 2.0 中的示例进行更新。

XSLT 2.0 组相邻

在 XSLT 2.0 中,您可以使用布尔值 true/false 作为相邻组的分组键,如下所示,这比上面的 XSLT 1.0 代码要短得多:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="2.0">

    <xsl:output indent="yes" />

    <xsl:template match="node() | @*">
        <xsl:copy>
            <xsl:apply-templates select="node() | @*" />
        </xsl:copy>
    </xsl:template>

    <xsl:template match="section">
        <xsl:copy>
            <xsl:for-each-group select="*" group-adjacent="starts-with(@id, 'ss')">
                <xsl:if test="current-grouping-key()"><ss_start /></xsl:if>
                <xsl:apply-templates select="current-group()" />
                <xsl:if test="current-grouping-key()"><ss_end /></xsl:if>
            </xsl:for-each-group>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

XSLT - 识别具有相同属性值模式的连续节点 的相关文章

随机推荐

  • 找不到满足版本约束的“androidx.arch.core:core-common”版本

    创建新的 Android Studio 项目 空活动类型 后 如果添加以下行 Lifecycle View Models def lifecycleVersion 2 0 0 implementation androidx lifecycl
  • 如何检测 MDIClient 窗口何时滚动

    当用户通过拖动 MDIS 客户端的滚动条拇指滚动子窗口时 我需要更新 System Windows Forms MDI 客户端容器内子窗口的位置 但是我找不到发生这种情况时触发的事件 我只是错过了它 还是我需要一个解决方法 可能是直接与滚动
  • elasticsearch python 客户端 - 与许多节点一起工作 - 如何使用嗅探器

    我有一个包含 2 个节点的集群 我试图了解连接节点的最佳实践 并在一个节点出现停机时检查故障转移 from 文档 http elasticsearch py readthedocs io en master api html nodes e
  • python 在html中显示unicode

    我正在编写脚本将我的链接及其标题从 chrome 导出到 html Chrome 书签以 json 形式存储 采用 utf 编码有些标题是俄语的 因此它们存储如下 名称 u0425 u0430 u0431 u0440 import code
  • 如何告诉 WebStorm 在 Docker 容器中查找项目?

    我当前的项目目录如下所示 backend Dockerfile NestJS Dockerfile docker Folder that contains docker compose yml file package json src f
  • ERLANG - 将列表拆分为子列表

    嗨 这是我在这里的第一篇文章 希望你们一切都好 所以我刚刚开始 erlang 我遇到了一个问题 我还不知道如何解决 所以我收到的二进制文件格式为 lt lt 56 23 67 34 45 78 01 54 67 87 45 53 01 34
  • Django REST 框架 JSONParser().parse(request) 引发错误

    在 Django 视图中 我正在尝试这样做 csrf exempt def customer list request List all customers or create a new customer if request metho
  • 在整个视图控制器中多次调用presentViewController方法会导致iOS中的内存泄漏吗?

    我知道已经有很多与这个主题相关的讨论 但在所有讨论中都讨论了 2 个视图控制器 A B 我的情况类似但又不同 当有多个视图控制器 如 A B C D 时会发生什么 所以呈现流程如下 视图控制器 A 主页 呈现视图控制器 B 列表 然后从视图
  • INSERT 语句中出现“此处不允许列”错误

    我创建了这个名为 LOCATION 的表 通过做这个 CREATE TABLE LOCATION POSTCODE VARCHAR 10 PRIMARY KEY STREET NAME VARCHAR 20 CITY VARCHAR 20
  • 在 FastCGI 和 Octave 中重新定义标准输出

    我正在努力在 Ubuntu Linux 中使用 C C 在 FastCGI 会话中实现 Octave 解释器 我遇到的问题是 FCGI 重定向stdout to FCGI 标准输出 但预编译的 Octave 头文件仍然使用正常的stdout
  • Flex:组合框控件的自定义项目渲染器截断文本

    我已经实现了一个自定义项目渲染器 我正在处理的 Flex 项目上将其与组合框一起使用 它显示每个项目的图标和一些文本 唯一的问题是 当文本较长时 菜单的宽度无法正确调整 并且文本在显示时会被截断 我尝试调整所有明显的属性来缓解这个问题 但没
  • 如何将图像保存到sqlite数据库

    在我的课程中 我有一个方法可以在照片库中搜索图像 并接收从手机摄像头拍摄的图像 我现在需要将此图像保存在 sqlite 数据库中 我正在使用像 BLOB 这样的数据库字段 但不像在 bity 中序列化图像或在decode64 中进行转换以写
  • 在 GraphQL 架构中使用数字作为键?

    您可以使用 GraphQL Schema 语言在 GraphQL Schema 中使用数字作为键吗 即 这是一个小片段 type tax code allocation country KOR states 11 tax code allo
  • 将 `:map` 的输出获取到缓冲区

    我想得到无参数的输出 map调用 以便我可以使用 vim 的搜索功能来查找映射 我发现关于 redir 它将 ex 命令的输出重定向到变量 寄存器或文件中 但它似乎不适用于 map 它必须以某种不同的方式输出映射 例如 echo hello
  • 如何使用可旁加载的证书创建 UWP 应用

    我正在尝试创建一个可以侧载到其他电脑上的 UWP 应用程序 我的主要问题是 我是否需要来自可信来源的证书来签署我的应用程序 经过大量研究后 我了解到您可以通过应用程序旁加载 安装 UWP 应用程序应用程序安装程序 https www mic
  • 中介者模式与创建

    我的演示文稿中有几个需要相互交互的 小部件 但交互已经变得足够复杂 需要一个新对象来处理交互 在尝试通过中介者作为该对象进行工作时 我对如何有效地构建参与者感到困惑 中介者必须了解小部件 而小部件也必须了解中介者 使用下面的玩具类 有人可以
  • jquery 日期时间选择器设置 minDate 动态

    我正在使用trentrichardson com 的日期时间选择器 我有一个带有两个输入字段的表单 from and to我希望能够动态地将 minDate 设置为我的 to 字段 等于我的 from 字段的值 我知道我应该使用 befor
  • 从 Unix 时间戳转换为 Groovy 中的日期

    我有一个 unix 时间戳中的日期 我想将其转换为人类可读的 def dateUnix 1486146877214 Date dateObj new Date long dateUnix 1000 def cleanDate new Sim
  • 加载了错误的 Java 资源包

    在我的应用程序中 我使用 java 资源包来翻译其标签 我目前有两个文件 带有英语标签的 resources properties 默认语言 带有法语标签的 resources fr properties 然后 我使用以下命令加载捆绑包属性
  • XSLT - 识别具有相同属性值模式的连续节点

    我有这样的xml section p aa p p bb p p cc p p dd p p ee p p ff p p gg p p hh p p ii p p jj p p xx p p p section