2013-02-17 53 views
2

XSLT遇到了一些问题..我想我可能会完全错误的解决这个问题.. 尝试在一行中显示具有特殊1状态的项目SKU的客户名称.. 。 然后用特殊的2项客户等则第2部分(我还没有开始)无状态的项目由自己XSLT有点困惑

所以这个XML文件的输出将

Joe prod1 //special1 
Joe prod3 //special2 
Joe prod2 //no status 
Joe prod4 //no status 
Joe prod5 //no status 
John Smith prod6 prod8 //special1 
John Smith prod7 //no status 
John Smith prod9 //no status 
John Smith prod10 //no status 

这种方法目前有效,但问题是,如果没有special1或special2,我不知道如何使它不打印客户的名字..

我不知道如何显示没有状态之后的任何 - 任何帮助将不胜感激!

XML:

<customer> 
<name>Joe</name> 
<order> 
    <item> 
     <SKU>prod1</SKU> 
     <status>special1</status> 
    </item> 
    <item> 
     <SKU>prod2</SKU> 
    </item> 
    <item> 
     <SKU>prod3</SKU> 
     <status>special2</status> 
    </item> 
    <item> 
     <SKU>prod4</SKU> 
    </item> 
    <item> 
     <SKU>prod5</SKU> 
    </item> 
</order> 
</customer> 
<customer 
<name>John Smith</name> 
<order> 
    <item> 
     <SKU>prod6</SKU> 
     <status>special1</status> 
    </item> 
    <item> 
     <SKU>prod7</SKU> 
    </item> 
    <item> 
     <SKU>prod8</SKU> 
     <status>special1</status> 
    </item> 
    <item> 
    <SKU>prod9</SKU> 
</item> 
    <item> 
     <SKU>prod10</SKU> 
    </item> 
</order> 

XSLT:

<!DOCTYPE xsl:stylesheet[ <!ENTITY nl "&#xd;&#xa;"> ]> 

<xsl:template match="customer"> 
    <xsl:value-of select="name" /><xsl:apply-templates select="order/item[status='special1']" /><xsl:text>&nl;</xsl:text> 
    <xsl:value-of select="name" /><xsl:apply-templates select="order/item[status='special2']" /><xsl:text>&nl;</xsl:text> 
</xsl:template> 

<xsl:template match="item[status='special1']"><xsl:text> </xsl:text><xsl:value-of select="SKU" /></xsl:template> 
<xsl:template match="item[status=special2']"><xsl:text> </xsl:text><xsl:value-of select="SKU" /></xsl:template> 

<xsl:template match="text()"/> 

+0

如果我是你,我会尝试做'嵌套的'和''元素循环。 – 2013-02-17 05:27:48

+0

我也试过这种方式..做一个为每个通过客户..显示名称,然后通过特殊状态的foreach,但我不明白如何不显示客户名称这样做,如果有没有特殊的状态项目! – Keiiz 2013-02-17 06:06:34

+0

好吧怎么样我只是使用一个if语句..叹了一个漫长的一天..我发誓我遇到了这样做的问题,这样做之前!但到目前为止这么好..感谢让我回到轨道上Jacob – Keiiz 2013-02-17 06:12:59

回答

0

你最简单的选择就是一个xsl:如果

<xsl:template match="customer"> 
    <xsl:if test="order/item[status='special1']"> 
     <xsl:value-of select="name" /><xsl:apply-templates select="order/item[status='special1']" /><xsl:text>&nl;</xsl:text> 
    </xsl:if> 
    <xsl:if test="order/item[status='special2']"> 
     <xsl:value-of select="name" /><xsl:apply-templates select="order/item[status='special2']" /><xsl:text>&nl;</xsl:text> 
    </xsl:if> 
</xsl:template> 
0

我假设你不知道先验设定的不同状态。所以,如果你wan't你的XML是维护(而不必在每次添加不同状态的时间去改变它),你可以采用如下方案:

<xsl:stylesheet version="1.0" 
       xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 

    <xsl:output method="text" /> 

    <!-- Use the following key for grouping --> 
    <xsl:key name="status-key" 
      match="item" 
      use="status" /> 

    <!-- Cache the following operation to avoid doing it several times in the future. 
     You can improve performance by changing // to a fixed path in your XML where 
     all the items are (e.g. /customers/customer/order/item) --> 
    <xsl:variable name="item-group" 
        select="//item[generate-id(.) = generate-id(key('status-key', status)[1])]" /> 


    <xsl:template match="customer"> 

     <!-- Obtain the following values before losing the current context --> 
     <xsl:variable name="current-id" select="generate-id(.)" /> 
     <xsl:variable name="current-name" select="name" /> 

     <!-- Display the products with a status defined --> 
     <xsl:for-each select="$item-group"> 
      <!-- Obtain list of status for this costumer --> 
      <xsl:variable name="customer-status" 
          select="key('status-key', status)[generate-id(../..) = $current-id]" /> 
      <!-- Print the status information if the costumer has at least one status --> 
      <xsl:if test="$customer-status"> 
       <!-- Display the name of the costumer --> 
       <xsl:value-of select="$current-name" /> 
       <!-- Group the product by status --> 
       <xsl:for-each select="$customer-status"> 
        <xsl:value-of select="concat(' ', SKU)" /> 
       </xsl:for-each> 
       <!-- Output the status --> 
       <xsl:value-of select="concat(' //', status, '&#xa;')" /> 
      </xsl:if> 
     </xsl:for-each> 

     <!-- Display the prodcuts without status --> 
     <xsl:for-each select="order/item[not(status)]"> 
      <xsl:value-of select="concat($current-name, ' ', SKU, ' //no-status&#xa;')" /> 
     </xsl:for-each> 

    </xsl:template> 

    <xsl:template match="text()" /> 

</xsl:stylesheet> 
0

这是一个“分组”的例子问题。您正尝试通过客户和地位的组合对项目进行分组。您使用XSLT 1.0或XSLT 2.0来解决此问题的方法有所不同。在XSLT 1.0中,您可以使用称为Muenchian Grouping的技术。你首先定义一个键来保存你正在分组的节点。在这种情况下,你是客户项目分组

<xsl:key name="items" match="item" use="concat(generate-id(../..), '|', status)" /> 

然后,你匹配每个客户元素,你会得到不同的状态,为每个项目元素,像这样:

<xsl:apply-templates select="order/item 
    [status != ''] 
    [generate-id() = generate-id(key('items', concat(generate-id(../..), '|', status))[1])]" /> 

从本质上讲这是什么做的是看每个项目,并选择您为状态元素定义的密钥中第一个出现的位置。

然后,在与状态相匹配的项目模板,就可以得到具有相同地位的个别项目,像这样:

<xsl:apply-templates select="key('items', concat(generate-id(../..), '|', status))/SKU" /> 

选择无状态的项目,虽然是很容易

<xsl:apply-templates select="order/item[not(status != '')]" /> 

以下是完整的XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="text"/> 
    <xsl:key name="items" match="item" use="concat(generate-id(../..), '|', status)" /> 

    <xsl:template match="customer"> 
     <xsl:apply-templates select="order/item[status != ''][generate-id() = generate-id(key('items', concat(generate-id(../..), '|', status))[1])]" /> 
     <xsl:apply-templates select="order/item[not(status != '')]" /> 
    </xsl:template> 

    <xsl:template match="item[status !='']"> 
     <xsl:value-of select="../../name" /> 
     <xsl:apply-templates select="key('items', concat(generate-id(../..), '|', status))/SKU" /> 
     <xsl:value-of select="concat(' //', status, '&#13;')" /> 
    </xsl:template> 

    <xsl:template match="item"> 
     <xsl:value-of select="concat(../../name, ' ', SKU, ' // no status&#13;')" /> 
    </xsl:template> 

    <xsl:template match="SKU"> 
     <xsl:value-of select="concat(' ', .)" /> 
    </xsl:template> 
</xsl:stylesheet> 

当适用于您的XML时,FOLL亏欠的是输出:

Joe prod1 //special1 
Joe prod3 //special2 
Joe prod2 // no status 
Joe prod4 // no status 
Joe prod5 // no status 
John Smith prod6 prod8 //special1 
John Smith prod7 // no status 
John Smith prod9 // no status 
John Smith prod10 // no status 

如果您正在使用XSLT2.0就显得有点简单跟随,因为你可以使我们的xsl:对,每个组处理分组:

<xsl:for-each-group select="order/item[status != '']" group-by="status"> 

然后让同组的项目,您使用当前组()功能

<xsl:apply-templates select="current-group()/SKU" /> 

这里全XSLT2.0样式表也应该输出同样的结果:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="text"/> 

    <xsl:template match="customer"> 
     <xsl:for-each-group select="order/item[status != '']" group-by="status"> 
      <xsl:value-of select="../../name" /> 
      <xsl:apply-templates select="current-group()/SKU" /> 
      <xsl:value-of select="concat(' //', status, '&#13;')" />   
     </xsl:for-each-group> 

     <xsl:apply-templates select="order/item[not(status != '')]" /> 
    </xsl:template> 

    <xsl:template match="item"> 
     <xsl:value-of select="concat(../../name, ' ', SKU, ' // no status&#13;')" /> 
    </xsl:template> 

    <xsl:template match="SKU"> 
     <xsl:value-of select="concat(' ', .)" /> 
    </xsl:template> 
</xsl:stylesheet>