简体   繁体   English

XSLT v1.0-Muenchian分组问题

[英]XSLT v1.0 - Muenchian Grouping Issue

I am having an issue while trying to aggregate xml duplicates while trying to produce a formatted pdf with XSL-FO, XSLT and Apache FOP. 我在尝试使用XSL-FO,XSLT和Apache FOP生成格式化的pdf时尝试聚合xml重复项时遇到问题。

I have already read a few posts about how to implement this with special look to post: XSLT and xpath v1.0 find duplicates and aggregate and also to the article Muenchian Grouping but still I face a problem. 我已经阅读了一些有关如何以特殊外观实现此目的的帖子: XSLT和xpath v1.0查找重复项并进行汇总,并且还可以阅读Muenchian Grouping文章,但仍然遇到问题。

My XML is the following: 我的XML是以下内容:

<Document>
    <RecordDetails>
        <Record>
            <contact id="0001" title="Mr" forename="John" surname="Smith" />
        </Record>
        <Record>
            <contact id="0002" title="Dr" forename= "Amy" surname="Jones" />
        </Record>
        <Record>    
            <contact id="0003" title="Mr" forename="Jack" surname="Smith" />
        </Record>
    </RecordDetails>
</Document>


What I am trying to implement is aggregate on my pdf formatted output all the contact items that that have the same value for the srname attribute. 我要实现的是在pdf格式的输出上聚合所有具有srname属性值的联系人项。 My current XSL code looks like that: 我当前的XSL代码如下所示:

<xsl:key name="contactsbysurname" match="contact" use="@surname"/> 


<xsl:template match="Record">
      *<xsl:for-each select="contact[generate-id(.)=generate-id(key('contactsbysurname',@surname)[1])]">
          <xsl:for-each select="key('contactsbysurname',@surname)"> *
            <fo:table-row font-size="6.5pt">                              
                  <xsl:apply-templates select="contact"/>
            </fo:table-row>     
          </xsl:for-each>
      </xsl:for-each>
</xsl:template>    


<xsl:template match="contact">
    <fo:table-cell>
        <fo:block text-align="center">
            <xsl:value-of select="@title" />
        </fo:block>
    </fo:table-cell>
    <fo:table-cell>
        <fo:block text-align="center">
            <xsl:value-of select="@Smith" />
        </fo:block>
    </fo:table-cell>
    <fo:table-cell>
        <fo:block text-align="center">
            ...
        </fo:block>
    </fo:table-cell>
</xsl:template> 

It seems that within the template Record when I try to include the 2 xsl:for-each loops in order to implement the Muenchian method, FOP returns me an error which involves that no fo:table-cell elements can be found inside the fo:table-row tag. 似乎在模板Record中,当我尝试包括2个xsl:for-each循环以实现Muenchian方法时,FOP向我返回了一个错误,该错误涉及在fo中找不到fo:table-cell元素:表行标记。 I understand this as the fact that FOP cannot access the first xsl:for-each loop and I wonder if I am doing something wrong. 我将其理解为FOP无法访问第一个xsl:for-each循环这一事实,我想知道自己是否做错了什么。

If I remove the 2 for-each tags I get my pdf but without the aggregation. 如果删除2个for-each标签,则会得到pdf,但没有聚合。 Am I missing something on the way I write my code ? 我在编写代码时是否缺少某些东西?

All help is very appreciated! 非常感谢所有帮助! Thank you. 谢谢。

It should work as you're expecting if you simply change this line: 如果仅更改以下行,它应该可以按您期望的那样工作:

<xsl:apply-templates select="contact"/>

to this: 对此:

<xsl:apply-templates select="."/>

However, I would propose structuring your XSLT more like this: 但是,我建议更像这样构造XSLT:

  <xsl:template match="Record">
    <xsl:apply-templates
      select="contact[generate-id() = 
                        generate-id(key('contactsbysurname',@surname)[1])]"
      mode="group" />
  </xsl:template>

  <xsl:template match="contact" mode="group">
    <xsl:apply-templates select="key('contactsbysurname',@surname)" />
  </xsl:template>

  <xsl:template match="contact">
    <fo:table-row font-size="6.5pt">
      <fo:table-cell>
        <fo:block text-align="center">
          <xsl:value-of select="@title" />
        </fo:block>
      </fo:table-cell>
      <fo:table-cell>
        <fo:block text-align="center">
          <xsl:value-of select="@surname" />
        </fo:block>
      </fo:table-cell>
      <fo:table-cell>
        <fo:block text-align="center">
          ...
        </fo:block>
      </fo:table-cell>
    </fo:table-row>
  </xsl:template>

Edit 编辑

If you just want to show one row of information for each contact, then there's no need to have two nestes for-each es or two layers of contact templates. 如果您只想为每个联系人显示一行信息,则无需for-each ES嵌套两层或两层contact模板。 In that case, it's even simpler: 在这种情况下,它甚至更简单:

  <xsl:template match="Record">
    <xsl:apply-templates
      select="contact[generate-id() = 
                        generate-id(key('contactsbysurname',@surname)[1])]" />
  </xsl:template>

  <xsl:template match="contact">
    <fo:table-row font-size="6.5pt">
      <fo:table-cell>
        <fo:block text-align="center">
          <xsl:value-of select="@title" />
        </fo:block>
      </fo:table-cell>
      <fo:table-cell>
        <fo:block text-align="center">
          <xsl:value-of select="@surname" />
        </fo:block>
      </fo:table-cell>
      <fo:table-cell>
        <fo:block text-align="center">
          ...
        </fo:block>
      </fo:table-cell>
    </fo:table-row>
  </xsl:template>

Change 更改

<xsl:template match="Record">
      *<xsl:for-each select="contact[generate-id(.)=generate-id(key('contactsbysurname',@surname)[1])]">
          <xsl:for-each select="key('contactsbysurname',@surname)"> *
            <fo:table-row font-size="6.5pt">                              
                  <xsl:apply-templates select="contact"/>
            </fo:table-row>     
          </xsl:for-each>
      </xsl:for-each>
</xsl:template>  

to

<xsl:template match="RecordDetails">
      <xsl:for-each select="Record/contact[generate-id(.)=generate-id(key('contactsbysurname',@surname)[1])]">
            <fo:table-row font-size="6.5pt">                              
                  <xsl:apply-templates select="key('contactsbysurname',@surname)"/>
            </fo:table-row>     
          </xsl:for-each>
      </xsl:for-each>
</xsl:template>  

That should give you one row for each group of contact with the same @surname . 这样应该为具有相同@surname每组contact @surname Then in each row you process all contact elements with the matching template. 然后在每一行中,使用匹配的模板处理所有contact元素。

And

<xsl:value-of select="@Smith" />

looks wrong as well as there are no attributes of that name in the input sample. 看起来错误,以及输入样本中没有该名称的属性。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM