如何使用 XSLT1 按标签折叠一组选定的(相邻)标签?

2023-12-03

我有一组必须包含在新元素中的顺序节点。例子:

  <root>
    <c>cccc</c>
    <a gr="g1">aaaa</a>    <b gr="g1">1111</b>
    <a gr="g2">bbbb</a>   <b gr="g2">2222</b>
  </root>

必须包含在fold标签,结果(在 XSLT 之后):

  <root>
    <c>cccc</c>
    <fold><a gr="g1">aaaa</a>    <b gr="g1">1111</b></fold>
    <fold><a gr="g2">bbbb</a>   <b gr="g2">2222</b></fold>
  </root>

所以,我有一个“分组标签”(@gr)但无法想象如何生成正确的折叠标签。


我正在尝试使用以下线索这个问题, or 另一个...但是我有一个“分组标签”,所以我知道我的解决方案不需要使用key()功能。

我的非通用解决方案是:

   <xsl:template match="/">
       <root>
       <xsl:copy-of select="root/c"/>
       <fold><xsl:for-each select="//*[@gr='g1']">
             <xsl:copy-of select="."/>
       </xsl:for-each></fold>

       <fold><xsl:for-each select="//*[@gr='g2']">
             <xsl:copy-of select="."/>
       </xsl:for-each></fold>

       </root>
   </xsl:template>

我需要一个通用的解决方案(!),循环所有 @gr 并应对(身份)所有没有 @gr 的上下文...也许使用身份转变.

另一个(未来的)问题是通过折叠的折叠来递归地执行此操作。


在 XSLT 1.0 中,处理此类事情的标准技术称为 Muenchian 分组,并且涉及使用key定义节点应如何分组以及使用的技巧generate-id仅提取每个组中的第一个节点作为整个组的代理。

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:strip-space elements="*" />
  <xsl:output indent="yes" />
  <xsl:key name="elementsByGr" match="*[@gr]" use="@gr" />

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

  <!-- match the first element with each @gr value -->
  <xsl:template match="*[@gr][generate-id() =
         generate-id(key('elementsByGr', @gr)[1])]" priority="2">
    <fold>
      <xsl:for-each select="key('elementsByGr', @gr)">
        <xsl:call-template name="identity" />
      </xsl:for-each>
    </fold>
  </xsl:template>

  <!-- ignore subsequent ones in template matching, they're handled within
       the first element template -->
  <xsl:template match="*[@gr]" priority="1" />
</xsl:stylesheet>

这实现了您想要的分组,但就像您的非通用解决方案一样,它不会保留缩进和之间的空白文本节点a and b元素,即它会给你

<root>
  <c>cccc</c>
  <fold>
    <a gr="g1">aaaa</a>
    <b gr="g1">1111</b>
  </fold>
  <fold>
    <a gr="g2">bbbb</a>
    <b gr="g2">2222</b>
  </fold>
</root>

请注意,如果您能够使用 XSLT 2.0,那么整个事情就变成了一个for-each-group:

<xsl:template match="root">
  <xsl:for-each-group select="*" group-adjacent="@gr">
    <xsl:choose>
      <!-- wrap each group in a fold -->
      <xsl:when test="@gr">
        <fold><xsl:copy-of select="current-group()" /></fold>
      </xsl:when>
      <!-- or just copy as-is for elements that don't have a @gr -->
      <xsl:otherwise>
        <xsl:copy-of select="current-group()" />
      </xsl:otherwise>
    </xsl:choose>
  </xsl:for-each-group>
</xsl:template>
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何使用 XSLT1 按标签折叠一组选定的(相邻)标签? 的相关文章

  • 使用 XSLT 对重复的 XML 数据进行分组

    我有一个 XML 需要转换为更好的项目分组 需要对物品进行计数 不知道会有多少只狗 出现在列表中 我可能不知道有多少关于 会有狗 在示例中有三个 但也可以是 任何数字 如果这不能灵活 那么固定数量也可以 最好是 XSLT 1 0 这可能吗
  • BaseX:在哪里声明要执行查询的 XML 文档

    通过 BaseX 程序 我能够使用 XPath 和 XQuery 来查询位于我的主目录中的 XML 文档 但在 XSLT 中执行相同操作时遇到问题 我查询的文档是书店Q xml https raw github com elexhobby
  • XSLT打开其他xml文件

    我即将合并 XML 文件 并添加元信息 其相对路径在我的输入 XML 文件中指定 我要合并的文件位于名为 files 的子目录中 输入文件的结构如下
  • WYSIWYG XML 编辑器(基于 DTD 或 RelaxNG 或 XSD 的语法)[关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 我需要为自定义 XML 语法创建一个
  • 如何在 C# 中启用 XSLT 脚本..?

    找到答案后我修改了问题的标题 P 我正在通过 C 程序加载 XML 文件和 XSL 文件并触发 XSL 转换 以下是其代码 static void Main string args Create the XslCompiledTransfo
  • 在c中使用xslt创建xml文件

    我有 5 个不同的键 值对 并且我知道我的 xml 文件应该是什么样子 我怎样才能用它创建一个 xml 文件 1 我总是可以做 printf 不太好 2 我可以使用 xslt 样式表 xsl 文件 来执行此操作吗 而且 我还希望能够进行我刚
  • XSLT 将平面树结构转换为列表

    我有一个描述eshop树结构的xml文件 我只需要获取所有子组的列表 我不知道结构中有多少个父 子级别 输入 xml 如下所示
  • 代码折叠未保存在我的 vimrc 中

    我将以下代码添加到我的 vimrc 中 save and restore folds when a file is closed and re opened autocmd BufWinLeave mkview autocmd BufWin
  • 随机推荐