按类别显示项目xml

时间:2009-06-24 15:26:26

标签: xml xslt

我有一个像这样的xml输出:

<data>
    <item-types>
        <entry id="1" items="5">
            <category>Frozen</category>
        </entry>
        <entry id="2" items="4">
            <category>Breakfast</category>
        </entry>
    </item-types>

    <items>
        <entry id="28">
            <item-number>1115</item-number>
            <name>Marion Berries, IQF</name>
            <area>
                <item id="1">Groceries - Frozen</item>
            </area>
        </entry>
        <entry id="29">
            <item-number>1117</item-number>
            <name>Peach Cups</name>
            <area>
                <item id="1">Groceries - Frozen</item>
            </area>
        </entry>
        <entry id="35">
            <item-number>1570</item-number>
            <name>Sausage Patty</name>
            <area>
                <item id="2">Groceries - Breakfast</item>
            </area>
        </entry>
        <entry id="32">
            <item-number>1575</item-number>
            <name>French Toast Stix, WG</name>
            <area>
                <item id="2">Groceries - Breakfast</item>
            </area>
        </entry>
    </items>
</data>

items-types是以下项目的类别。 item-types/entry/@iditems/entry/area/item/@id直接相关,我正在尝试将项目整理到输出的类别中。

到目前为止,我正在使用以下XSL转换。

<xsl:template match="item-types/entry">
    <h3><xsl:value-of select="concat(@id,'. ',category)" /></h3>
    <ul>
        <xsl:apply-templates select="/data/items/entry[area/item/@id = @id]" />
    </ul>
</xsl:template>
<xsl:template match="items/entry">
    <li>
        <xsl:value-of select="concat(item-number,'. ',name,' (',area/item/@id,')')" />
    </li>
</xsl:template>

问题是它不起作用。我认为问题是转换第4行的谓词:[area/item/@id = @id]当我删除它时,它会显示每个类别中的所有项目。

有没有办法在“冻结”类别中显示“冻结”项目,在“早餐”类别中显示“早餐”项目?

谢谢!

1 个答案:

答案 0 :(得分:4)

使用XSL密钥轻松完成。

<xsl:key name="kEntryByAreaId" match="items/entry" use="area/item/@id" />

<!-- this is just for the sake of the test -->
<xsl:template match="/data">
  <xsl:apply-templates select="item-types/entry" />
</xsl:template>

<xsl:template match="item-types/entry">
  <h3>
    <xsl:value-of select="concat(@id,'. ',category)" />
  </h3>
  <ul>
    <xsl:apply-templates select="key('kEntryByAreaId', @id)" />
  </ul>
</xsl:template>

<xsl:template match="items/entry">
  <li>
    <xsl:value-of select="
      concat(
        item-number, 
        '. ', name,
        ' (', area/item/@id, ')'
      )
    " />
  </li>
</xsl:template>

现在回答为什么你的尝试不起作用的问题。

这个表达式:

/data/items/entry[area/item/@id = @id]

说:“所有/data/items/entry元素的area/item/@id值等于其@id值”。麻烦的是 - 他们没有@id值。

你的意思是这样的:

/data/items/entry[area/item/@id = current()/@id]

这样可行,但关键会更快。