<xsl:template match="location">
<xsl:if test="not(preceding::location)">
<table>
<tr>
<th>Name</th>
<th>City</th>
<th>State</th>
<th>Zip Code</th>
<th>Country</th>
</tr>
</xsl:if>
<tr>
<td><xsl:value-of select=".//name"/></td>
<td><xsl:value-of select=".//city"/></td>
<td><xsl:value-of select=".//state"/></td>
<td><xsl:value-of select=".//zip"/></td>
<td><xsl:value-of select=".//countdy"/></td>
</tr>
<xsl:if test="not(following::location)">
</table>
</xsl:if>
</xsl:template>
Run Code Online (Sandbox Code Playgroud)
是否允许在XSLT中使用不匹配的标签...或者是否有其他方法可以实现相同的预期效果?
就像Dimitre所说,没有办法在XSLT中允许不匹配的标签.不过应该没有理由让标签不匹配.
查看您的模板,看起来您正在尝试从<location>
XML实例的所有元素构建一个html表.你试图在第一次打开表<location>
并尝试在最后关闭表<location>
.
最简单的方法是在更高级别(父级/祖级)打开表,然后使用<location>
数据填充表.
这是一个有3 <location>
s 的示例XML文件:
<doc>
<location>
<name>name 1</name>
<city>city 1</city>
<state>state 1</state>
<zip>zip 1</zip>
<country>country 1</country>
</location>
<location>
<name>name 2</name>
<city>city 2</city>
<state>state 2</state>
<zip>zip 2</zip>
<country>country 2</country>
</location>
<location>
<name>name 3</name>
<city>city 3</city>
<state>state 3</state>
<zip>zip 3</zip>
<country>country 3</country>
</location>
</doc>
Run Code Online (Sandbox Code Playgroud)
这是一个将创建表的样式表:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="doc">
<!--The table is inserted here.-->
<table>
<tr>
<th>Name</th>
<th>City</th>
<th>State</th>
<th>Zip Code</th>
<th>Country</th>
</tr>
<!--This is where we apply the templates to populate the rows.-->
<xsl:apply-templates select="location"/>
</table>
</xsl:template>
<!--This template populates the row(s).-->
<xsl:template match="location">
<tr>
<td>
<xsl:value-of select="name"/>
</td>
<td>
<xsl:value-of select="city"/>
</td>
<td>
<xsl:value-of select="state"/>
</td>
<td>
<xsl:value-of select="zip"/>
</td>
<td>
<xsl:value-of select="country"/>
</td>
</tr>
</xsl:template>
</xsl:stylesheet>
Run Code Online (Sandbox Code Playgroud)
这是输出:
<table>
<tr>
<th>Name</th>
<th>City</th>
<th>State</th>
<th>Zip Code</th>
<th>Country</th>
</tr>
<tr>
<td>name 1</td>
<td>city 1</td>
<td>state 1</td>
<td>zip 1</td>
<td>country 1</td>
</tr>
<tr>
<td>name 2</td>
<td>city 2</td>
<td>state 2</td>
<td>zip 2</td>
<td>country 2</td>
</tr>
<tr>
<td>name 3</td>
<td>city 3</td>
<td>state 3</td>
<td>zip 3</td>
<td>country 3</td>
</tr>
</table>
Run Code Online (Sandbox Code Playgroud)
如果由于某种原因你需要创建<table>
第一个<location>
,你仍然可以这样做.但它需要更多代码.
以下样式表生成与第一个样式表相同的输出:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/doc">
<xsl:apply-templates/>
</xsl:template>
<!--The table is created at the first location and
the first row is populated.-->
<xsl:template match="location[1]">
<table>
<tr>
<th>Name</th>
<th>City</th>
<th>State</th>
<th>Zip Code</th>
<th>Country</th>
</tr>
<xsl:call-template name="location-row"/>
<!--Here is where we apply the other template to populate the other rows.
Notice we use a "mode" to differentiate the template from the generic
"location" template.-->
<xsl:apply-templates select="following-sibling::location" mode="not-first"/>
</table>
</xsl:template>
<!--This template will output the other rows.-->
<xsl:template match="location" mode="not-first" name="location-row">
<tr>
<td>
<xsl:value-of select="name"/>
</td>
<td>
<xsl:value-of select="city"/>
</td>
<td>
<xsl:value-of select="state"/>
</td>
<td>
<xsl:value-of select="zip"/>
</td>
<td>
<xsl:value-of select="country"/>
</td>
</tr>
</xsl:template>
<!--This generic template matches locations other than the first one.
Basically it is consuming it so we don't get duplicate output.-->
<xsl:template match="location"/>
</xsl:stylesheet>
Run Code Online (Sandbox Code Playgroud)