我是XSLT的新手,我正在尝试将xml下面的数据解析为html,其中每个根/ Quote / Quotes是一个Vehicle,Vehicle的值是根据相应报价中的QuoteId确定的,我需要显示Quote-1&amp;的相应值。报价-2,QuoteID低于第一<Sequence>
&amp;第二个<Sequence>
并排基于QuoteID,我需要显示所有根/报价/报价中的所有不同元素及其值,或者是否有任何元素或元素的值不存在 - 我需要显示“未找到”
第一个<Sequence>
可能有<SequenceID>
的1,2,3和第二个<Sequence>
可以拥有{/ 1 / /引号/引号{ {1}} 1&amp; 3,在这种情况下,我需要显示Quote-2的所有标签值为&#39; Not Found&#39;
输入XML
<SequenceID>
所需输出
<HTMLData>
<Sequence>
<QuoteTitle>Quote-1</QuoteTitle>
<Response>
<root>
<Quotes>
<Quote>
<Element1 value="122"/>
<Element2 value="233"/>
<Element3 value="344"/>
<Element4 value="455"/>
<QuoteID value="1"/>
</Quote>
</Quotes>
<Quotes>
<Quote>
<Element1 value="466"/>
<Element2 value="577"/>
<Element7 value="688"/>
<Element8 value="799"/>
<QuoteID value="2"/>
</Quote>
</Quotes>
</root>
</Response>
</Sequence>
<Sequence>
<QuoteTitle>Quote-2</QuoteTitle>
<Response>
<root>
<Quotes>
<Quote>
<Element1 value="233"/>
<Element10 value=""/>
<Element11 value=""/>
<Element12 value="123"/>
<QuoteID value="1"/>
</Quote>
</Quotes>
<Quotes>
<Quote>
<Element13 value="123"/>
<Element14 value="234"/>
<Element15 value="456"/>
<QuoteID value="2"/>
<Element16 value="654"/>
</Quote>
</Quotes>
<Quotes>
<Quote>
<Element13 value="234"/>
<Element14 value="443"/>
<Element15 value="654"/>
<Element16 value="544"/>
<QuoteID value="3"/>
</Quote>
</Quotes>
</root>
</Response>
</Sequence>
</HTMLData>
&#13;
答案 0 :(得分:0)
您正在将输入中的行转换为输出中的列,并且您正在查找可能未包含在每个<Quote>
中的元素。
要对此进行管理,您需要列出所有可能的元素名称和<Quotes>
的最大数量。
然后,您可以按Quotes
循环查看position()
列表,并查找$elements
列表中的所有元素。
完整的解决方案:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common" exclude-result-prefixes="exsl"
version="1.0">
<xsl:output method="html"/>
<xsl:key name="element-key" match="//root/Quotes/Quote/*" use="name()" />
<!-- collect all posible element-names -->
<xsl:variable name="elements">
<xsl:for-each select="//root/Quotes/Quote/*">
<xsl:if test="generate-id() = generate-id(key('element-key', name())[1])">
<xsl:apply-templates mode="elements" select="."/>
</xsl:if>
</xsl:for-each>
</xsl:variable>
<xsl:template match="Quote/*" mode="elements">
<element>
<xsl:attribute name="name"><xsl:value-of select="name()"/></xsl:attribute>
</element>
</xsl:template>
<xsl:variable name="vehicleCount">
<xsl:call-template name="vehicleCount">
<xsl:with-param name="nodelist" select="//root"></xsl:with-param>
</xsl:call-template>
</xsl:variable>
<xsl:template name="vehicleCount">
<xsl:param name="nodelist" />
<xsl:choose>
<xsl:when test="count($nodelist) > 0">
<xsl:variable name="countFirst" select="count(exsl:node-set($nodelist[1])/Quotes)"/>
<xsl:variable name="maxRest">
<xsl:call-template name="vehicleCount">
<xsl:with-param name="nodelist" select="exsl:node-set($nodelist[position()>1])" />
</xsl:call-template>
</xsl:variable>
<xsl:choose>
<xsl:when test="$countFirst > $maxRest"><xsl:value-of select="$countFirst"/></xsl:when>
<xsl:otherwise><xsl:value-of select="$maxRest"/></xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="0"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:variable name="quoteTitles">
<xsl:copy-of select="/HTMLData/Sequence/QuoteTitle"/>
</xsl:variable>
<xsl:variable name="sequences">
<xsl:copy-of select="/HTMLData/Sequence"/>
</xsl:variable>
<xsl:template match="/">
<table>
<tr>
<th class="border-top border-bottom border-left border-right">Type</th>
<th class="border-top border-bottom border-left border-right">Vehicle</th>
<th class="border-top border-bottom border-left border-right">Label</th>
<xsl:for-each select="exsl:node-set($quoteTitles)/*">
<th class="border-top border-bottom border-left border-right"><xsl:value-of select="text()"/></th>
</xsl:for-each>
</tr>
<xsl:call-template name="outputVehicle"/>
</table>
</xsl:template>
<xsl:template name="outputVehicle">
<xsl:param name="pos">1</xsl:param>
<xsl:for-each select="exsl:node-set($elements)/*">
<xsl:variable name="elementName" select="@name"/>
<tr>
<xsl:choose>
<xsl:when test="$elementName = exsl:node-set($elements)/*[1]/@name">
<td class="border-top border-bottom border-left border-right">Motor</td>
<td class="border-top border-bottom border-left border-right">Vehicle<xsl:value-of select="$pos"/></td>
</xsl:when>
<xsl:otherwise>
<td class="border-top border-bottom border-left border-right"></td>
<td class="border-top border-bottom border-left border-right"></td>
</xsl:otherwise>
</xsl:choose>
<td class="border-top border-bottom border-left border-right"><xsl:value-of select="$elementName"/></td>
<xsl:for-each select="exsl:node-set($quoteTitles)/*">
<xsl:variable name="quoteTitle" select="text()"/>
<xsl:variable name="quote" select="exsl:node-set($sequences)/*[QuoteTitle=$quoteTitle]/Response/root/Quotes[position()=$pos]/Quote/*[name()=$elementName]/@value" />
<td class="border-top border-bottom border-left border-right">
<xsl:choose>
<xsl:when test="$quote"><xsl:value-of select="$quote"/></xsl:when>
<xsl:otherwise>Not Found</xsl:otherwise>
</xsl:choose>
</td>
</xsl:for-each>
</tr>
</xsl:for-each>
<xsl:if test="$pos < $vehicleCount">
<!-- wonder if xslt-processors are able to do tail-call optimization... -->
<xsl:call-template name="outputVehicle"><xsl:with-param name="pos" select="$pos+1" /></xsl:call-template>
</xsl:if>
</xsl:template>
</xsl:stylesheet>