使用 XSLT 1.0 进行复杂分组 [英] Complex Grouping using XSLT 1.0

查看:38
本文介绍了使用 XSLT 1.0 进行复杂分组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经修改了数据文件并添加了一个分组列.否则我无法弄清楚分组的逻辑.

I've revised the data file and added a Grouping column. I could not figure out a logic for grouping otherwise.

数据包含邮票收藏的信息.

The data contains information for a stamp collection.

这是示例 XML:

<?xml version="1.0" encoding="UTF-8"?>
<stamps>        
<stamp>     
<Group>25</Group>       
<Scott>3133</Scott>     
<Title>32¢ Thornton Wilder</Title>      
<Series>Literary Arts</Series>      
</stamp>        
<stamp>     
<Group>26</Group>       
<Scott>3134</Scott>     
<Title>32¢ Charlie Chaplin</Title>      
</stamp>
<stamp>     
<Group>26</Group>       
<Scott>3135</Scott>     
<Title>32¢ Raoul Wallenberg</Title>     
</stamp>
<stamp>     
<Group>27</Group>       
<Scott>3136</Scott>     
<Title>Sheet of 15</Title>      
<Issue>The World of Dinosaurs</Issue>       
</stamp>        
<stamp>     
<Group>27</Group>       
<Scott>3136</Scott>     
<Minor>a</Minor>        
<Title>32¢ Ceratosaurus</Title>     
<Issue>The World of Dinosaurs</Issue>       
</stamp>        
<stamp>     
<Group>27</Group>       
<Scott>3136</Scott>     
<Minor>b</Minor>        
<Title>32¢ Camptosaurus</Title>     
<Issue>The World of Dinosaurs</Issue>       
</stamp>        
<stamp>     
<Group>27</Group>       
<Scott>3136</Scott>     
<Minor>c</Minor>        
<Title>32¢ Camarasaurus</Title>     
<Issue>The World of Dinosaurs</Issue>       
</stamp></stamps>

这是我放在一起的 XSLT:

Here is the XSLT I put together:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>

<xsl:key name="StampGroup" match="stamp" use="Group"/>
<xsl:key name="ScottGroup" match="stamp" use="concat(Group, '|', Scott)"/>

<xsl:template match="/*">
 <xsl:copy>
  <xsl:apply-templates select="stamp[generate-id() = generate-id(key('StampGroup', Group)[1])]" mode="StampGroup" />
 </xsl:copy>
 </xsl:template>

<xsl:template match="stamp" mode="StampGroup">
<StampGroup id="{Group}">        

<xsl:apply-templates select="key('StampGroup', Group)[generate-id() = generate-id(key('ScottGroup', concat(Group, '|', Scott))[1])]" mode="ScottGroup" />
</StampGroup>
</xsl:template>

<xsl:template match="stamp" mode="ScottGroup">
 <stamp>
  <Scott><xsl:value-of select="Scott"/></Scott>
  <Title><xsl:value-of select="Title"/></Title>
  <Minor><xsl:value-of select="Minor"/></Minor> 
 </stamp>
</xsl:template>

</xsl:stylesheet>

这是生成的 XML:

<?xml version="1.0" encoding="utf-8"?>
<stamps>
<StampGroup id="25">
  <stamp>
     <Scott>3133</Scott>
     <Title>32¢ Thornton Wilder</Title>
     <Minor/>
  </stamp>
</StampGroup>
<StampGroup id="26">
  <stamp>
     <Scott>3134</Scott>
     <Title>32¢ Charlie Chaplin</Title>
     <Minor/>
  </stamp>
  <stamp>
     <Scott>3135</Scott>
     <Title>32¢ Raoul Wallenberg</Title>
     <Minor/>
   </stamp>
  <stamp>
     <Scott>3136</Scott>
     <Title>Sheet of 15</Title>
     <Minor/>
  </stamp>
 </StampGroup>
</stamps>

大部分时间都在工作.它正在拉动组.它正在提取 UNIQUE <Scott> 项目,但它没有提取 <Minor> 子项目.

It's mostly working. It's pulling the groups. It's pulling UNIQUE <Scott> items, but it's not picking up the <Minor> subitems.

我以前从未使用过这种类型的 XSLT 结构.你如何让它像 for-each 一样重复项目?

I've never used this type of XSLT structure before. How do you get it to repeat items as in for-each?

第 27 组中有 4 个项目.它们都具有相同的 编号,但具有不同的 字段.

Group 27 has 4 items in it. They all have the same <Scott> number but different <Minor> fields.

我需要创建第三个密钥吗?

Do I need to create a third key?

抱歉,忘记添加想要的结果:

Sorry, forgot to add the desired result:

<?xml version="1.0" encoding="utf-8"?>
<stamps>
<StampGroup id="25">
  <stamp>
     <Scott>3133</Scott>
     <Title>32¢ Thornton Wilder</Title>
     <Minor/>
  </stamp>
</StampGroup>
<StampGroup id="26">
  <stamp>
     <Scott>3134</Scott>
     <Title>32¢ Charlie Chaplin</Title>
     <Minor/>
  </stamp>
  <stamp>
     <Scott>3135</Scott>
     <Title>32¢ Raoul Wallenberg</Title>
     <Minor/>
  </stamp>
</StampGroup>
<StampGroup id="27">
  <stamp>
     <Scott>3136</Scott>
     <Title>Sheet of 15</Title>
     <Minor/>
  </stamp>
  <stamp>
     <Scott>3136</Scott>
     <Title>32¢ Ceratosaurus</Title>
     <Minor>a</Minor>       
  </stamp>
  <stamp>
     <Scott>3136</Scott>
     <Title>32¢ Camptosaurus</Title>    
     <Minor>b</Minor>       
  </stamp>
  <stamp>
     <Scott>3136</Scott>
     <Title>32¢ Camarasaurus</Title>
     <Minor>c</Minor>       
  </stamp>
 </StampGroup>
</stamps>

推荐答案

如果您希望每个 Group 中只有唯一的 Scott 值,并且只有唯一的 每个 Scott 子组中的次要 值,那么是的,您将需要三个键.

If you want to have only unique Scott values within each Group, and only unique Minor values within each Scott subgroup, then yes, you will need three keys.

如果您要作为子组的值对于每个父组不是唯一的,则必须连接键以将键缩小到仅匹配当前父组的项目.

And if the values by which you want to subgroup are not unique to each parent group, then the keys will have to be concatenated in order to narrow the key down to matching items from the current parent group only.

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:key name="stamp-by-group" match="stamp" use="Group" />
<xsl:key name="stamp-by-scott" match="stamp" use="concat(Group, '|', Scott)" />
<xsl:key name="stamp-by-minor" match="stamp" use="concat(Group, '|', Scott, '|', Minor)" />

<xsl:template match="/stamps">
    <xsl:copy>
        <xsl:for-each select="stamp[count(. | key('stamp-by-group', Group)[1]) = 1]">
            <StampGroup id="{Group}">
                <xsl:for-each select="key('stamp-by-group', Group)[count(. | key('stamp-by-scott', concat(Group, '|', Scott))[1]) = 1]">
                    <xsl:apply-templates select="key('stamp-by-scott', concat(Group, '|', Scott))[count(. | key('stamp-by-minor', concat(Group, '|', Scott, '|', Minor))[1]) = 1]"/>
                </xsl:for-each>
            </StampGroup>
        </xsl:for-each>
    </xsl:copy>
</xsl:template>

<xsl:template match="stamp">
    <xsl:copy>
        <xsl:copy-of select="Scott | Title"/>
        <Minor><xsl:value-of select="Minor" /></Minor>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

<小时>

如果您没有通过 Scott 为组创建任何内容,那么您可以跳过二级分组及其关联键,直接进入三级分组:


If you're not creating anything for the group by Scott, then you can skip the secondary grouping and its associated key, and go directly to the tertiary grouping:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:key name="stamp-by-group" match="stamp" use="Group" />
<xsl:key name="stamp-by-minor" match="stamp" use="concat(Group, '|', Scott, '|', Minor)" />

<xsl:template match="/stamps">
    <xsl:copy>
        <xsl:for-each select="stamp[count(. | key('stamp-by-group', Group)[1]) = 1]">
            <StampGroup id="{Group}">
                <xsl:apply-templates select="key('stamp-by-group', Group)[count(. | key('stamp-by-minor', concat(Group, '|', Scott, '|', Minor))[1]) = 1]"/>
            </StampGroup>
        </xsl:for-each>
    </xsl:copy>
</xsl:template>

<xsl:template match="stamp">
    <xsl:copy>
        <xsl:copy-of select="Scott | Title"/>
        <Minor><xsl:value-of select="Minor" /></Minor>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

这篇关于使用 XSLT 1.0 进行复杂分组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆