使用 XSLT 1.0 的逗号分隔子组和组

Posted

技术标签:

【中文标题】使用 XSLT 1.0 的逗号分隔子组和组【英文标题】:Comma Separated Child Group with Group, using XSLT 1.0 【发布时间】:2016-04-23 15:18:39 【问题描述】:

在我的 XSLT 脚本中添加逗号分隔组时遇到问题。 “Insured”列是包含子标签的目标字段,我想将这些子标签作为逗号分隔的字符串添加到我的报告中。

预期的 O/P:

Client Sum Insured Report

UK
SNo.    Policy Number   Customer Name   Cover Note #    Insured           No. of Addendas Sum Insured Total Commission
 1       POL1           ABC             50242           INSA, INS2, INS1    2               40000       65
 2       POL2           XYZ             12345           INSB, INS3          1               30000       30
Totals :                                                                                   70000       95

US
SNo.    Policy Number   Customer Name   Cover Note #    Insured           No. of Addendas Sum Insured Total Commission
 1                      JKL             45678           INSC                0               10000       10
Totals :                                                                                  10000       10

XML:

<?xml version="1.0" encoding="UTF-8"?><?Siebel-Property-Set EscapeNames="true"?><SiebelMessage MessageId="1-OC05" IntObjectName="Client Sum Insured Report IO" MessageType="Integration Object" IntObjectFormat="Siebel Hierarchical">
<ListOfGroupPolicies>
<GroupPolicies>
 <Addenda>50242-1</Addenda>
 <CommAmt>50</CommAmt>
 <Cover>50242</Cover>
 <Customer>ABC</Customer>
 <Policy>POL1</Policy>
 <SumInsured>10000</SumInsured>
 <InsuredAccnt>INSA</InsuredAccnt>
 <Organization>UK</Organization>
 <ListOfGroupPolicies_Insured>
  <GroupPolicies_Insured>
  <InsuredAccount>INS1</InsuredAccount>
  <InsuredShare>5</InsuredShare>
  </GroupPolicies_Insured>
  <GroupPolicies_Insured>
  <InsuredAccount>INS2</InsuredAccount>
  <InsuredShare>25</InsuredShare>
  </GroupPolicies_Insured>
 </ListOfGroupPolicies_Insured>
</GroupPolicies>
<GroupPolicies>
 <Addenda>50242-2</Addenda>
 <CommAmt>5</CommAmt>
 <Cover>50242</Cover>
 <Customer>ABC</Customer>
 <Policy>POL1</Policy>
 <SumInsured>20000</SumInsured>
 <InsuredAccnt>INSA</InsuredAccnt>
 <Organization>UK</Organization>
 <ListOfGroupPolicies_Insured>
  <GroupPolicies_Insured>
  <InsuredAccount>INS1</InsuredAccount>
  <InsuredShare>5</InsuredShare>
  </GroupPolicies_Insured>
  <GroupPolicies_Insured>
  <InsuredAccount>INS2</InsuredAccount>
  <InsuredShare>25</InsuredShare>
  </GroupPolicies_Insured>
 </ListOfGroupPolicies_Insured>
</GroupPolicies>
<GroupPolicies>
 <Addenda></Addenda>
 <CommAmt>10</CommAmt>
 <Cover>50242</Cover>
 <Customer>ABC</Customer>
 <Policy>POL1</Policy>
 <SumInsured>10000</SumInsured>
 <InsuredAccnt>INSA</InsuredAccnt>
 <Organization>UK</Organization>
 <ListOfGroupPolicies_Insured>
  <GroupPolicies_Insured>
  <InsuredAccount>INS1</InsuredAccount>
  <InsuredShare>5</InsuredShare>
  </GroupPolicies_Insured>
  <GroupPolicies_Insured>
  <InsuredAccount>INS2</InsuredAccount>
  <InsuredShare>25</InsuredShare>
  </GroupPolicies_Insured>
 </ListOfGroupPolicies_Insured>
</GroupPolicies>
<GroupPolicies>
 <Addenda>12345-1</Addenda>
 <CommAmt>20</CommAmt>
 <Cover>12345</Cover>
 <Customer>XYZ</Customer>
 <Policy>POL2</Policy>
 <SumInsured>20000</SumInsured>
 <InsuredAccnt>INSB</InsuredAccnt>
 <Organization>UK</Organization>
 <ListOfGroupPolicies_Insured>
  <GroupPolicies_Insured>
  <InsuredAccount>INS3</InsuredAccount>
  <InsuredShare>20</InsuredShare>
  </GroupPolicies_Insured>
 </ListOfGroupPolicies_Insured>
</GroupPolicies>
<GroupPolicies>
 <Addenda></Addenda>
 <CommAmt>10</CommAmt>
 <Cover>12345</Cover>
 <Customer>XYZ</Customer>
 <Policy>POL2</Policy>
 <SumInsured>10000</SumInsured>
 <InsuredAccnt>INSB</InsuredAccnt>
 <Organization>UK</Organization>
 <ListOfGroupPolicies_Insured>
  <GroupPolicies_Insured>
  <InsuredAccount>INS3</InsuredAccount>
  <InsuredShare>20</InsuredShare>
  </GroupPolicies_Insured>
 </ListOfGroupPolicies_Insured>
</GroupPolicies>
<GroupPolicies>
 <Addenda></Addenda>
 <CommAmt>10</CommAmt>
 <Cover>45678</Cover>
 <Customer>JKL</Customer>
 <Policy></Policy>
 <SumInsured>10000</SumInsured>
 <InsuredAccnt>INSC</InsuredAccnt>
 <Organization>US</Organization>
 <ListOfGroupPolicies_Insured />
</GroupPolicies>
</ListOfGroupPolicies>

使用 XSLT:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" indent="yes"/>      
<xsl:template match="/SiebelMessage/ListOfGroupPolicies">
    <xsl:text>&#09;&#09;</xsl:text>
    <xsl:text>Client Sum Insured Report</xsl:text>
    <xsl:text>&#10;</xsl:text>
    <xsl:apply-templates select="GroupPolicies[not(preceding-sibling::GroupPolicies/Organization = Organization)]/Organization" />
</xsl:template>
<xsl:template match="GroupPolicies" >
    <xsl:variable name="count" select="position()"/>
    <xsl:value-of select="$count"/>
    <xsl:text>&#09;</xsl:text>
    <xsl:value-of select="Policy"/>
    <xsl:text>&#09;</xsl:text>
    <xsl:value-of select="Customer"/>
    <xsl:text>&#09;</xsl:text>
    <xsl:value-of select="Cover"/>
    <xsl:text>&#09;</xsl:text>
    <xsl:value-of select="InsuredAccount"/> <!-- Comma Separated List of Insured Accounts per Cover-->
    <xsl:text>&#09;</xsl:text>
    <xsl:value-of select="count(../GroupPolicies[Organization=current()/Organization and Cover=current()/Cover]/Addenda[string-length()>0])"/>
    <xsl:text>&#09;</xsl:text>
    <xsl:value-of select="sum(../GroupPolicies[Organization=current()/Organization and Cover=current()/Cover]/SumInsured)"/>
    <xsl:text>&#09;</xsl:text>
    <xsl:value-of select="sum(../GroupPolicies[Organization=current()/Organization and Cover=current()/Cover]/CommAmt)"/> 
    <xsl:text>&#10;</xsl:text>            
</xsl:template>  
<xsl:template match="Organization">
    <xsl:text>&#10;</xsl:text>
    <xsl:text>SNo.</xsl:text>
    <xsl:text>&#09;</xsl:text>
    <xsl:text>Policy Number</xsl:text>
    <xsl:text>&#09;</xsl:text>
    <xsl:text>Customer Name</xsl:text>
    <xsl:text>&#09;</xsl:text>
    <xsl:text>Cover Note #</xsl:text>
    <xsl:text>&#09;</xsl:text>
    <xsl:text>Insured</xsl:text>
    <xsl:text>&#09;</xsl:text>
    <xsl:text>No. of Addendas</xsl:text>
    <xsl:text>&#09;</xsl:text>
    <xsl:text>Sum Insured</xsl:text>
    <xsl:text>&#09;</xsl:text>
    <xsl:text>Total Commission</xsl:text>
    <xsl:text>&#10;</xsl:text>
    <xsl:variable name="temp" select="." />         
    <xsl:apply-templates select="//GroupPolicies[Organization = current() and not(preceding-sibling::GroupPolicies/Cover=Cover)]"/>
    <xsl:text>Totals:</xsl:text>
    <xsl:text>&#09;&#09;&#09;&#09;&#09;&#09;&#09;&#09;&#09;&#09;&#09;&#09;&#09;</xsl:text><xsl:value-of select="sum(../../GroupPolicies[Organization=current()]/SumInsured)"/>
    <xsl:text>&#09;</xsl:text>
    <xsl:value-of select="sum(../../GroupPolicies[Organization=current()]/CommAmt)"/>
</xsl:template>
</xsl:stylesheet>

如果可能的话,有人可以帮助我吗?

【问题讨论】:

【参考方案1】:
    <xsl:value-of select="InsuredAccnt"/>
    <xsl:for-each select="ListOfGroupPolicies_Insured/GroupPolicies_Insured">
        <xsl:sort select="InsuredShare" order="descending" data-type="number"/>
        <xsl:text>, </xsl:text>
        <xsl:value-of select="InsuredAccount"/>
    </xsl:for-each>

这就是您在&lt;xsl:for-each&gt; 中进行排序的方式。

【讨论】:

非常感谢。上帝保佑【参考方案2】:

第一件事,而不是

<xsl:value-of select="InsuredAccount"/>

您必须使用完整的相对路径(从当前的&lt;GroupPolicies&gt; 元素开始):

<xsl:value-of select="ListOfGroupPolicies_Insured/GroupPolicies_Insured/InsuredAccount"/>

访问&lt;InsuredAccount&gt; 元素。但是,您仍然只会在每个 &lt;GroupPolicies&gt; 项目中获得第一次出现。因此,为了获取 所有 值并用逗号分隔它们,您应该使用

<xsl:for-each select="ListOfGroupPolicies_Insured/GroupPolicies_Insured/InsuredAccount">
    <xsl:value-of select="."/>
    <xsl:if test="not(position()=last())">, </xsl:if>
</xsl:for-each>

【讨论】:

OP 的代码实际上对初学者来说还不错,没有理由粗鲁。始终将文本放在 xsl:text: &lt;xsl:text&gt;, &lt;/xsl:text&gt; 中会更安全。 没有粗鲁的意思。 谢谢Kimmy,我想不用科学家就能猜出我是初学者!更糟糕的是,XSLT 超出了我的 Job Profile 的范围,这是一项一次性的任务。甚至现有的代码也是由一个好心的 *** 成员编写的。我不得不承认 XSLT 有点令人兴奋,尤其是当我看到格式精美的输出时。再次感谢。 @Matthias,感谢您的支持,但我还不是初学者,现有的不是我写的:(...记下“, " 是的,您可以使用 XSLT 做很多事情,而且这项技术的最佳之处在于它非常“兼容”,即它可以在各种平台上运行而无需进行任何修改。

以上是关于使用 XSLT 1.0 的逗号分隔子组和组的主要内容,如果未能解决你的问题,请参考以下文章

XSLT 将嵌套的 xml 元素写为一个带有逗号分隔值字符串的元素

如何使用 XSLT/XPath 生成逗号分隔的列表?

XSLT(2.0 或 3.0)方法将存储在 xml 中的每个逗号分隔值的整个 xml 复制到单独的 xml 文件中

使用 fscanf 读取逗号分隔的双精度

XSLT 处理引号和管道分隔符号

XSLT 映射以删除内部具有 PIPE 分隔符号的双引号