根据共享属性/值输出两个单独的节点组

时间:2014-12-19 14:39:05

标签: xml xslt xpath apply-templates

我想首先说我不擅长XPATH,这是我向你们寻求帮助的主要原因。

所以我今天正在努力尝试" group",或者说,基于他们两个共享ID的XML文件中的一些数据。在朋友的帮助下,我设法做到了这一点,但这是漫长的啰嗦,我确信必须有一个更简单/更清洁的方式。下面是我使用的XML,XSLT和所需的输出:

 <Dude>
     <ID>768</ID>
     <Name>Mr Dude Man</Name>
 </Dude>
 ...
 <Basket>
      <CustomerID>768</CustomerID>
      <Purchases>
          <PurchasedItem>
              <ItemID>736383-2</ItemID>
              <ItemName>XSLT Training</ItemName>
              <ItemType>Book</ItemType>
              <ItemQuantity>2</ItemQuantity>
          </PurchasedItem>
          <PurchasedItem>
              <ItemID>736383-2</ItemID>
              <ItemName>Candy</ItemName>
              <ItemType>Consumable</ItemType>
              <ItemQuantity>1</ItemQuantity>
          </PurchasedItem>
      </Purchases>
 </Basket>

我使用的XSLT:

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

<xsl:template match="Dude">
    {Name} has purchased: 
    <xsl:apply-templates select="Basket[Basket/CustomerID = ../Dude/ID]"/>
</xsl:template>

<xsl:template match="Basket">
    {ItemName}
</xsl:template>

在上面的示例中,每个Dude都可以有一个篮子,篮子上有一个customerID,用于识别篮子所有者。假设两个节点彼此一样深。我将如何使用<apply-templates/>上的xpath来产生以下结果:

PS。不要太担心实际输出,我只是想知道在使用apply-templates

在其中一个节点上匹配时遍历XML树的正确方法
Mr Dude Man has purchased: XSLT Training, Candy 

编辑:忘记我使用的XSLT ......现在我感到困惑的是,这是最好的方法吗?有两个单独的比赛。同样在谓词中我需要../或谓词假设我从匹配的位置开始,例如:Dude

1 个答案:

答案 0 :(得分:2)

像这样进行交叉引用的有效方法是使用密钥:

<xsl:key name='kBasket' match="Basket" use="CustomerID" />

然后你可以这样做:

<xsl:template match="/">
    <xsl:apply-templates select="/Full/Path/To/Dude" />
</xsl:template>

<xsl:template match="Dude">
    {Name} has purchased: 
    <xsl:apply-templates select="key('kBasket', ID)"/>
</xsl:template>

<xsl:template match="Basket">
    <-- Any per-basket stuff could be output here -->
    <xsl:apply-templates select="Purchases/PurchasedItem" />
</xsl:template>

<xsl:template match="PurchasedItem">
    <xsl:value-of select="ItemName" />
</xsl:template>

<小时/> 原始尝试的问题在于谓词中的所有路径都与Basket相关(并且您没有到达Basket的必要路径,因此节点集已经为空在那时候)。正确的方法是这样的:

<xsl:apply-templates select="/Absolute/Path/To/Basket[CustomerID = current()/ID]"/>

但关键方法更可取,因为它更有效。