我在使用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标记。
更新
以下两个示例都运行良好,但它们都包括root中的名称空间,这是意外的。我得到的输出是:
<?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"
?
答案 0 :(得分: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>
答案 1 :(得分:0)
为了吐出'largeimage'和'smallimage'元素(在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>
答案 2 :(得分:0)
在XSLT 1.0中,(IMO)最直接的解决方案是首先找到所有唯一ID。这可以通过查找未出现在任何先前兄弟节点中的ID来实现(换句话说,对于每个ID,您找到包含该ID的第一个元素)。
拥有唯一ID后,您可以<xsl:for-each>
覆盖具有相同ID的所有<row>
兄弟姐妹(包括当前元素)。在下面的代码中,我使用<xsl:choose>
元素检查<column2>
并根据<largeImage>
值插入<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>