2

我有一个这样的 xml 文件:

<products>
    <cars>
        <car>
            <brand>Audi</brand>
            <type>S3</type>
            <attribs>
                <attrib>
                    <color>1</color>
                    <price>45000</price>
                </attrib>
                <attrib>
                    <color>2</color>
                    <price>75000</price>
                </attrib>
                <attrib>
                    <color>4</color>
                    <price>35000</price>
                </attrib>
            </attribs>      
        </car>

        <!-- Many cars following -->

    </cars>
    <colors>
        <color>
            <id>1</id>
            <shortdesc>Blue</shortdesc>
            <description>Blue Lagoon</description>
        </color>
        <color>
            <id>2</id>
            <shortdesc>Red</shortdesc>
            <description>Red Sport</description>
        </color>
        <color>
            <id>3</id>
            <shortdesc>Green</shortdesc>
            <description>Green Forest</description>
        </color>
        <color>
            <id>4</id>
            <shortdesc>Yellow</shortdesc>
            <description>Yellow</description>
        </color>
                <!-- many colors -->
    </colors>
</products>

我正在将这个 XML 转换为一个 excel 交叉表,其中汽车在垂直方向,颜色在水平方向,如下所示:

Brand / Model       1/Blue   2/Red   3/Green   4/Yellow

Audi S3             45000    75000   -         35000    
Audi S6             66000    68000   59000     -
Jaguar x-type       98000    -       99500     -

xslt 看起来像:

<ss:Table>
    <ss:Row>
        <!-- This is the header row -->
        <ss:Cell>
            <ss:Data ss:Type="String">Brand / Model</ss:Data>
        </ss:Cell>
        <xsl:for-each select="colors/color">
            <ss:Cell>
                <ss:Data ss:Type="String">
                    <xsl:value-of select="id"/>/<xsl:value-of select="shortdesc"/>
                </ss:Data>
            </ss:Cell>
        </xsl:for-each>
    </ss:Row>
    <xsl:for-each select="cars/car">
        <ss:Row>
            <ss:Cell>
                <ss:Data ss:Type="String">
                    <xsl:value-of select="brand"/> <xsl:value-of select="type"/>
                </ss:Data>
            </ss:Cell>
            <xsl:for-each select="attribs/attrib">
                <!-- I Know this is incorrect, but what to put in the if ? -->
                <xsl:if test="color = /colors/color/id">
                    <ss:Cell>
                        <ss:Data ss:Type="String">
                            <xsl:value-of select="price"/>
                        </ss:Data>
                    </ss:Cell>
                </xsl:if>
                <xsl:if test="color != /colors/color/id">
                    <ss:Cell>
                        <ss:Data ss:Type="String">-</ss:Data>
                    </ss:Cell>
                </xsl:if>
            </xsl:for-each>
        </ss:Row>
    </xsl:for-each>
</ss:Table>

我正在寻找在右栏中比较/写价格的方法。

该模板引用节点 /products 以便能够访问汽车和颜色。一种可能的方法是在我在标题中写入颜色的同时创建一个数组,并在处理汽车时与它进行比较;这是一种可能的方法还是可能有更好的方法?

另一个细节:我无法更改 XML,因为它已经像这样设计了(实际上我正在处理的不是汽车,只是为了让它更简单)

4

1 回答 1

3

您可以使用复合键按品牌、类型和颜色收集汽车:

<xsl:output indent="yes"/>
<xsl:key name="k_cars" 
    match="/products/cars/car/attribs/attrib" 
    use="concat(../../brand,../../type,color)"/>

然后进行迭代cars/car,因为您需要检查所有颜色的价格(有些汽车可能会漏掉一种颜色),所以在密钥上进行子迭代colors/color并使用xsl:choose测试。如果key返回一个节点,则打印相应的价格;否则打印-

<xsl:variable name="car" select="."/>

<xsl:for-each select="/products/colors/*">

    <xsl:variable name="v_CarColor" 
        select="key('k_cars',concat($car/brand,$car/type,id))"/>

    <xsl:choose>

        <xsl:when test="$v_CarColor">
            <ss:Cell>
                <ss:Data ss:Type="String">
                    <xsl:value-of select="$v_CarColor/price"/>
                </ss:Data>
            </ss:Cell>
        </xsl:when>

        <xsl:otherwise>
            <ss:Cell>
                <ss:Data ss:Type="String">-</ss:Data>
            </ss:Cell>
        </xsl:otherwise>

    </xsl:choose>
</xsl:for-each>

您的最终转换:

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

    <xsl:output indent="yes"/>
    <xsl:key name="k_cars" 
        match="/products/cars/car/attribs/attrib" 
        use="concat(../../brand,../../type,color)"/>

    <xsl:template match="/products">
        <ss:Table>
            <ss:Row>
                <!-- This is the header row -->
                <ss:Cell>
                    <ss:Data ss:Type="String">Brand / Model</ss:Data>
                </ss:Cell>
                <xsl:for-each select="colors/color">
                    <ss:Cell>
                        <ss:Data ss:Type="String">
                            <xsl:value-of select="id"/>/<xsl:value-of select="shortdesc"/>
                        </ss:Data>
                    </ss:Cell>
                </xsl:for-each>
            </ss:Row>

            <xsl:for-each select="cars/car">

                <ss:Row>
                    <ss:Cell>
                        <ss:Data ss:Type="String">
                            <xsl:value-of select="brand"/> <xsl:value-of select="type"/>
                        </ss:Data>
                    </ss:Cell>


                    <xsl:variable name="car" select="."/>

                    <xsl:for-each select="/products/colors/*">

                        <xsl:variable name="v_CarColor" 
                            select="key('k_cars',concat($car/brand,$car/type,id))"/>

                        <xsl:choose>

                            <xsl:when test="$v_CarColor">
                                <ss:Cell>
                                    <ss:Data ss:Type="String">
                                        <xsl:value-of select="$v_CarColor/price"/>
                                    </ss:Data>
                                </ss:Cell>
                            </xsl:when>

                            <xsl:otherwise>
                                <ss:Cell>
                                    <ss:Data ss:Type="String">-</ss:Data>
                                </ss:Cell>
                            </xsl:otherwise>

                        </xsl:choose>
                    </xsl:for-each>
                </ss:Row>
            </xsl:for-each>
        </ss:Table> 
    </xsl:template>

</xsl:stylesheet>
于 2011-08-05T20:36:14.187 回答