【问题标题】:XSL Grouping of elements based on attribute value matched with wildcard基于与通配符匹配的属性值的 XSL 元素分组
【发布时间】:2012-12-20 09:45:18
【问题描述】:

我想转换这个 xml 片段

<Sets>
    <Set id="category.product.typeA.item1"/>
    <Set id="category.product.typeB.item2"/>
    <Set id="category.product.typeC.item3"/>
    <Set id="category.product.typeA.item2"/>
    <Set id="category.product.typeA.item3"/>
    <Set id="category.service.typeA.item1"/>
    <Set id="category.service.typeA.item2"/>
    <Set id="category.product.typeA.item4"/>
    <Set id="category.product.typeA.item5"/>
</Sets>

进入以下 xml 片段:

<Category id="category.product">
    <Group id="category.product.typeA">
        <Set id="category.product.typeA.item1"/>
        <Set id="category.product.typeA.item2"/>
        <Set id="category.product.typeA.item3"/>
        <Set id="category.product.typeA.item4"/>
        <Set id="category.product.typeA.item5"/>        
    </Group>
    <Group id="category.product.typeB"> 
        <Set id="category.product.typeB.item2"/>
    </Group>
    <Group id="category.product.typeC"> 
        <Set id="category.product.typeC.item3"/>
    </Group>
</Category>
<Category id="category.service">
    <Group id="category.service.typeA">
        <Set id="category.service.typeA.item1"/>
        <Set id="category.service.typeA.item2"/>
    </Group>
</Category>

基本上,我想根据属性值将元素分成不同的组。

所以,属性值匹配的元素: category.product.typeA.* 应该放在一组 category.product.typeB.* 应该放在另一个组中

如果属性的值与 category.product.* 匹配,则该组应归入一个类别,如果属性的值与 category.service.* 匹配,则应将其归入另一个类别。

我已经努力使用“starts-with”和“for-each-group”,但我无法将元素的分组和属性的通配符匹配放在一起,希望能提供任何帮助。

【问题讨论】:

    标签: xslt


    【解决方案1】:

    这是我的建议:

    <xsl:stylesheet
      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
      xmlns:xs="http://www.w3.org/2001/XMLSchema"
      xmlns:mf="http://example.com/mf"
      exclude-result-prefixes="xs mf"
      version="2.0">
    
    <xsl:output indent="yes"/>
    
    <xsl:template match="Sets">
      <xsl:for-each-group select="Set" group-by="string-join(tokenize(@id, '\.')[position() lt 3], '.')">
        <Category id="{current-grouping-key()}">
          <xsl:for-each-group select="current-group()" group-by="string-join(tokenize(@id, '\.')[position() lt 4], '.')">
            <Group id="{current-grouping-key()}">
              <xsl:copy-of select="current-group()"/>
            </Group>
          </xsl:for-each-group>
        </Category>
      </xsl:for-each-group>
    </xsl:template>
    
    </xsl:stylesheet>
    

    当我将 Saxon 9.4 的样式表应用于您的输入时,我得到了想要的结果

    <Category id="category.product">
       <Group id="category.product.typeA">
          <Set id="category.product.typeA.item1"/>
          <Set id="category.product.typeA.item2"/>
          <Set id="category.product.typeA.item3"/>
          <Set id="category.product.typeA.item4"/>
          <Set id="category.product.typeA.item5"/>
       </Group>
       <Group id="category.product.typeB">
          <Set id="category.product.typeB.item2"/>
       </Group>
       <Group id="category.product.typeC">
          <Set id="category.product.typeC.item3"/>
       </Group>
    </Category>
    <Category id="category.service">
       <Group id="category.service.typeA">
          <Set id="category.service.typeA.item1"/>
          <Set id="category.service.typeA.item2"/>
       </Group>
    </Category>
    

    【讨论】:

    • 非常感谢!我从来没有想过“tokenize”,但我一定会将 tokenize 添加到我的“xsl 工具箱”中。
    猜你喜欢
    • 1970-01-01
    • 2012-05-09
    • 2011-10-16
    • 1970-01-01
    • 2021-09-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-21
    相关资源
    最近更新 更多