1

我在使用 XML 并对其应用多个条件时遇到了一些问题。我有一个如下所示的输入 XML:

<?xml version="1.0" encoding="UTF-8"?>
<results xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ResultsType">
    <result>
        <resultSets>
            <resultSet>
                <row>
                    <column1>11111</column1>
                    <column2>0</column2>
                    <column3>imageId/111111</column3>
                    <column4>2012-04-03T10:11:22.187</column4>
                </row>
                <row>
                    <column1>11111</column1>
                    <column2>2</column2>
                    <column3>imageId/111112</column3>
                    <column4>2012-04-03T10:11:22.187</column4>
                </row>
                <row>
                    <column1>11111</column1>
                    <column2>2</column2>
                    <column3>imageId/111113</column3>
                    <column4>2012-04-03T10:11:22.187</column4>
                </row>
                <row>
                    <column1>22222</column1>
                    <column2>0</column2>
                    <column3>imageId/222222</column3>
                    <column4>2012-04-03T10:11:22.187</column4>
                </row>
                <row>
                    <column1>22222</column1>
                    <column2>2</column2>
                    <column3>imageId/222223</column3>
                    <column4>2012-04-03T10:11:22.187</column4>
                </row>
            </resultSet>
        </resultSets>
    </result>
</results>

但是我希望它看起来像这样:

<?xml version="1.0" encoding="UTF-8"?>
<results xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ResultsType">
    <result>
        <row>
            <id>11111</id>
            <lagrgeImage>imageId/111111</lagrgeImage>
            <smallImage>imageId/111112</smallImage>
            <smallImage>imageId/111113</smallImage>
        </row>
        <row>
            <id>22222</id>
            <lagrgeImage>imageId/222222</lagrgeImage>
            <smallImage>imageId/222223</smallImage>
        </row>
    </result>
</results>

如您所见,有两个过滤条件:

如果 column2 = 0 则输出中需要 largeImage 标记,但是 column2 = 2 则输出中需要 smallImage 标记。

更新

下面的两个示例都运行良好,但是它们都在根目录中包含了意想不到的命名空间。我得到的输出是:

<?xml version="1.0" encoding="utf-8"?>
<results xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ResultsType">
    <result>
        <row>
            <id>11111</id>
            <largeImage>imageId/111111</largeImage>
            <smallImage>imageId/111112</smallImage>
            <smallImage>imageId/111113</smallImage>
        </row>
        <row>
            <id>22222</id>
            <largeImage>imageId/222222</largeImage>
            <smallImage>imageId/222223</smallImage>
        </row>
    </result>
</results>

如何xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ResultsType"从上述输出中删除?

4

3 回答 3

1

如果您使用的是 XSLT2.0,则可以使用for-each-group函数。

<xsl:for-each-group select="row" group-by="column1">

假设您的上下文是resultSets这将按column1中的“id”对行进行分组。然后可以按如下方式获得当前分组密钥:

<xsl:value-of select="current-grouping-key()"/>

要获取组中的各个行,将它们转换为 largeImage 或 smallImage,您可以这样做

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

这是完整的 XSLT

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

   <xsl:output method="xml" indent="yes"/>

   <xsl:template match="resultSets">
      <xsl:apply-templates select="@*|node()"/>
   </xsl:template>

   <xsl:template match="resultSet">
      <xsl:apply-templates select="@*"/>
      <xsl:for-each-group select="row" group-by="column1">
         <row>
            <id><xsl:value-of select="current-grouping-key()"/></id>
            <xsl:apply-templates select="current-group()" />
          </row>
      </xsl:for-each-group>
   </xsl:template>

   <xsl:template match="row[column2='0']">
      <largeImage><xsl:value-of select="column3" /></largeImage>
   </xsl:template>

   <xsl:template match="row">
      <smallImage><xsl:value-of select="column3" /></smallImage>
   </xsl:template>

   <xsl:template match="@*|node()[not(self::*)]">
      <xsl:copy> 
         <xsl:apply-templates select="@*|node()"/>
      </xsl:copy>
   </xsl:template>

   <xsl:template match="*">
      <xsl:element name="{local-name()}"> 
         <xsl:apply-templates select="@*|node()"/>
      </xsl:element>
   </xsl:template>
</xsl:stylesheet>

应用于您的示例 XML 时,将输出以下内容

<results xmlns="http://www.castiron.com//response">
   <result>
      <row>
         <id>11111</id>
         <largeImage>imageId/111111</largeImage>
         <smallImage>imageId/111112</smallImage>
         <smallImage>imageId/111113</smallImage>
      </row>
      <row>
         <id>22222</id>
         <largeImage>imageId/222222</largeImage>
         <smallImage>imageId/222223</smallImage>
      </row>
   </result>
</results>
于 2012-06-28T15:29:34.527 回答
0

在 XSLT 1.0 中,(IMO)最直接的解决方案是首先找到所有唯一 ID。这可以通过查找没有出现在任何前面的兄弟姐妹中的 ID 来实现(换句话说,对于每个 ID,您会找到包含该 ID 的第一个元素)。

一旦你有了一个唯一的 ID,你就可以<xsl:for-each>覆盖所有<row>具有相同 ID 的兄弟姐妹(包括当前元素)。在下面的代码中,我使用了一个<xsl:choose>元素来检查并根据值<column2>插入一个<largeImage>or元素。<smallImage><column2>

这可以满足您的需求:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes"/>

    <xsl:template match="/results">
        <results>
            <xsl:copy-of select="@*"/>
            <result>
                <xsl:apply-templates select="result"/>
            </result>
        </results>
    </xsl:template>

    <xsl:template match="/results/result/resultSets/resultSet/row">
        <xsl:if test="not(column1 = preceding-sibling::row/column1)">
            <row>
                <id><xsl:value-of select="column1"/></id>
                <xsl:for-each select="../row[column1 = current()/column1]">
                    <xsl:choose>
                        <xsl:when test="column2 = '0'">
                            <largeImage><xsl:value-of select="column3"/></largeImage>
                        </xsl:when>
                        <xsl:when test="column2 = '2'">
                            <smallImage><xsl:value-of select="column3"/></smallImage>
                        </xsl:when>
                    </xsl:choose>
                </xsl:for-each>
            </row>
        </xsl:if>
    </xsl:template>

</xsl:stylesheet>
于 2012-06-28T15:15:55.397 回答
0

要吐出“大图像”和“小图像”元素(在 xsl for 循环中),请尝试:

<xsl:if test="/results/result/resultSets/resultSet/row/column2='0'">
<largeImage>
<xsl:value-of select="/results/result/resultSets/resultSet/row/column3"/>
</largeImage>    
</xsl:if>
于 2012-06-28T15:10:00.963 回答