0

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

所以我今天正在努力尝试“分组”,或者可以说,来自 XML 文件的一些数据基于它们共享一个 ID。在朋友的帮助下,我设法做到了这一点,但它相当冗长,我敢肯定一定有一个更简单/更清洁的方法。下面是我使用的 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连接到它以识别篮子所有者。假设两个节点彼此一样深。我将如何在 上使用 xpath<apply-templates/>来产生以下结果:

附言。不要太担心实际输出,我只想知道在使用其中一个节点进行匹配时遍历 XML 树的正确方法apply-templates

Mr Dude Man has purchased: XSLT Training, Candy 

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

4

1 回答 1

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]"/>

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

于 2014-12-19T15:18:45.497 回答