XSLT:如何选择祖先(不是根)独有的元素?

时间:2012-02-17 19:19:26

标签: xslt sorting key

我正在寻找一种从根目录下方的祖先元素中选择一组唯一节点的方法。我的简化输入如下所示(注意:<Single>中可能有多个<Multi><Package>元素:

<Package>
  <Single>
    <Patient>
      <Drug>
        <Name>A</Name>
        <Dose>1 tab</Dose>
      </Drug>
      <Drug>
        <Name>B</Name>
        <Dose>2 spoonfuls</Dose>
      </Drug>
    </Patient>
  </Single>
  <Multi>
    <Patient>
      <Drug>
        <Name>A</Name>
        <Dose>1 tab</Dose>
      </Drug>
      <Drug>
        <Name>B</Name>
        <Dose>2 spoonfuls</Dose>
      </Drug>
      <Drug>
        <Name>C</Name>
        <Dose>3 drops</Dose>
      </Drug>
    </Patient>
    <Patient>
      <Drug>
        <Name>B</Name>
        <Dose>2 spoonfuls</Dose>
      </Drug>
      <Drug>
        <Name>B</Name>
        <Dose>2 spoonfuls</Dose>
      </Drug>
      <Drug>
        <Name>C</Name>
        <Dose>3 drops</Dose>
      </Drug>
      <Drug>
        <Name>D</Name>
        <Dose>4 glasses</Dose>
      </Drug>
    </Patient>
  </Multi>
</Package>

我想为每个<Single><Multi>元素选择唯一符合<Patient>的药物。到目前为止,我有:

  <xsl:template match="/">
    <xsl:for-each select="Package/Single | Package/Multi">
      <xsl:call-template name="SO" />
    </xsl:for-each>
  </xsl:template>

  <xsl:key name="uniqueKey" match="//Patient/Drug" use="concat(Name, Dose)" />

  <xsl:template name="SO">
    <UniquePerMultiOrSingle>
      <xsl:for-each select="//Patient/Drug[
                              generate-id() =
                              generate-id(key('uniqueKey', concat(Name, Dose))[1])]">
        <xsl:copy-of select="Name"/>
        <xsl:copy-of select="Dose"/>
      </xsl:for-each>
    </UniquePerMultiOrSingle>
  </xsl:template>

输出如下:

<UniquePerMultiOrSingle>
  <Name>A</Name>
  <Dose>1 tab</Dose>
  <Name>B</Name>
  <Dose>2 spoonfuls</Dose>
  <Name>C</Name>
  <Dose>3 drops</Dose>
  <Name>D</Name>
  <Dose>4 glasses</Dose>
</UniquePerMultiOrSingle>
<UniquePerMultiOrSingle>
  <Name>A</Name>
  <Dose>1 tab</Dose>
  <Name>B</Name>
  <Dose>2 spoonfuls</Dose>
  <Name>C</Name>
  <Dose>3 drops</Dose>
  <Name>D</Name>
  <Dose>4 glasses</Dose>
</UniquePerMultiOrSingle>

所需的输出应如下所示:

<UniquePerMultiOrSingle>
  <Name>A</Name>
  <Dose>1 tab</Dose>
  <Name>B</Name>
  <Dose>2 spoonfuls</Dose>
</UniquePerMultiOrSingle>
<UniquePerMultiOrSingle>
  <Name>A</Name>
  <Dose>1 tab</Dose>
  <Name>B</Name>
  <Dose>2 spoonfuls</Dose>
  <Name>C</Name>
  <Dose>3 drops</Dose>
  <Name>D</Name>
  <Dose>4 glasses</Dose>
</UniquePerMultiOrSingle>

我的问题:有没有办法选择<Drug>唯一<Single><Multi>元素(不是整个文档)?如果没有,有没有其他方法来实现这一目标?我正在使用xslt 1.0。

1 个答案:

答案 0 :(得分:0)

此转化

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:key name="kPackageDrugsByName" match="Drug"
  use="concat(generate-id(../..), '+', Name, '+', Dose)"/>

 <xsl:template match="Single | Multi">
  <xsl:text>&#xA;</xsl:text>
  <xsl:value-of select="name()"/> -- Drugs:&#xA;<xsl:text/>

  <xsl:copy-of select=
   "*/Drug
       [generate-id()
       =
        generate-id(key('kPackageDrugsByName',
                        concat(generate-id(../..),
                               '+', Name, '+', Dose)
                       )[1]
                   )
       ]/*"/>
 </xsl:template>
</xsl:stylesheet>

应用于提供的XML文档

<Package>
    <Single>
        <Patient>
            <Drug>
                <Name>A</Name>
                <Dose>1 tab</Dose>
            </Drug>
            <Drug>
                <Name>B</Name>
                <Dose>2 spoonfuls</Dose>
            </Drug>
        </Patient>
    </Single>
    <Multi>
        <Patient>
            <Drug>
                <Name>A</Name>
                <Dose>1 tab</Dose>
            </Drug>
            <Drug>
                <Name>B</Name>
                <Dose>2 spoonfuls</Dose>
            </Drug>
            <Drug>
                <Name>C</Name>
                <Dose>3 drops</Dose>
            </Drug>
        </Patient>
        <Patient>
            <Drug>
                <Name>B</Name>
                <Dose>2 spoonfuls</Dose>
            </Drug>
            <Drug>
                <Name>B</Name>
                <Dose>2 spoonfuls</Dose>
            </Drug>
            <Drug>
                <Name>C</Name>
                <Dose>3 drops</Dose>
            </Drug>
            <Drug>
                <Name>D</Name>
                <Dose>4 glasses</Dose>
            </Drug>
        </Patient>
    </Multi>
</Package>

生成想要的正确结果

Single -- Drugs:
<Name>A</Name>
<Dose>1 tab</Dose>
<Name>B</Name>
<Dose>2 spoonfuls</Dose>

Multi -- Drugs:
<Name>A</Name>
<Dose>1 tab</Dose>
<Name>B</Name>
<Dose>2 spoonfuls</Dose>
<Name>C</Name>
<Dose>3 drops</Dose>
<Name>D</Name>
<Dose>4 glasses</Dose>