[英]Is it possible to transform a parsimonious XML to a full HTML table using XSLT 2.0?
VERY IMPORTANT NOTE: I am using QtXmlPattern (a not fully implemented XSLT 2.0 processor with a few bugs in what's implemented...) 非常重要的说明:我正在使用QtXmlPattern(未完全实现的XSLT 2.0处理器,在实现的内容中存在一些错误...)
I have a well formed XML file with data defined in a four level array as in: 我有一个格式良好的XML文件,其数据在四级数组中定义,如下所示:
<a>
<b>
<c day="20150221">
<d>...</d>
<e>...</e>
</c>
<c day="20150222">
<d>...</d>
<e>...</e>
</c>
<c day="20150223">
<d>...</d>
<e>...</e>
</c>
</b>
<b>
<c day="20150219">
<d>...</d>
<e>...</e>
</c>
<c day="20150221">
<d>...</d>
<e>...</e>
</c>
<c day="20150223">
<d>...</d>
<e>...</e>
</c>
</b>
...
</a>
The result should include all the days, but as we can see each <b>
list may have a different set of days. 结果应包括所有天数,但正如我们看到的那样,每个<b>
列表可能都有不同的天数集。 Yet the result needs to have all the days for all the <b>
tags. 但是结果需要所有<b>
标签全天候运行。 If data is not available, the result remains empty or zero as might be. 如果没有数据,则结果可能为空或为零。
I found a way to gather all the days in a variable: 我找到了一种收集变量中所有天数的方法:
<xsl:variable name="days" select="distinct-values(/a/b/c/@day)"/>
But I don't see how to generate the final results which would look something like this: 但是我看不到如何生成最终结果,就像下面这样:
<table>
<th>
<td>20150219</td>
<td>20150221</td>
<td>20150222</td>
<td>20150223</td>
</th>
<tr>
<td>data from <d> tag on 20150219</td>
<td>data from <d> tag on 20150221</td>
<td>data from <d> tag on 20150222</td>
<td>data from <d> tag on 20150223</td>
</tr>
...[repeat for various data and calculation on the data]...
</table>
My problem is that the variable is not a list of nodes, just a list of strings and I'm not too sure how I can loop through a list of string. 我的问题是变量不是节点列表,而是字符串列表,我不太确定如何遍历字符串列表。
Just in case, for those who do not know about the QXmlQuery parser, the xsl:for-each-group
command does not exist. 以防万一,对于那些不了解QXmlQuery解析器的人, xsl:for-each-group
命令不存在。
You can (with XSLT 2.0, not sure whether your chosen processor supports that then) simply do 您可以(使用XSLT 2.0,不确定所选择的处理器是否支持该功能)就可以了
<xsl:variable name="main-doc" select="/">
to store the main document node in a variable you will later on, then define a key 将主文档节点存储在稍后将要定义的变量中,然后定义一个键
<xsl:key name="by-date" match="a/b/c/d" use="../@day"/>
and then references d
items on a day with 然后在一天中引用d
项目
<xsl:for-each select="$days">
<xsl:variable name="d-on-day" select="key('by-date', ., $main-doc)"/>
That key()
call with three argument is new in XSLT 2.0, if not supported then try 带有三个参数的那个key()
调用是XSLT 2.0中的新功能,如果不支持,请尝试
<xsl:for-each select="$days">
<xsl:variable name="day" select="."/>
<xsl:for-each select="$main-doc">
<xsl:variable name="d-on-day" select="key('by-date', $day)"/>
...
</xsl:for-each>
...
</xsl:for-each>
If the key
function is not available then you need to write the references as eg 如果key
功能不可用,则需要编写引用,例如
<xsl:variable name="d-elements" select="/a/b/c/d"/>
<xsl:for-each select="$days">
<xsl:variable name="day" select="."/>
<xsl:for-each select="$d-elements[../@day = $day]">...</xsl:for-each>
</xsl:for-each>
I am not exactly sure what you need, but sometimes it is easier to comment on an attempted solution than trying to explain. 我不确定您需要什么,但有时对尝试的解决方案发表评论要比尝试解释容易。 You definitely have to use a key to find distinct attribute values. 您绝对必须使用键来查找不同的属性值。
Do not loop through a list of strings, but through a sequence of c
elements that are unique with respect to the value of their day
attribute (which, in the end, is the same). 不要遍历字符串列表,而是遍历一系列c
元素,这些元素相对于其day
属性的值是唯一的(最后是相同的)。 The technique I use below is described by Jeni Tennison here because it is commonly used for grouping problems. 我在下面使用的技术由Jeni Tennison进行了描述,因为它通常用于分组问题。
XML Input XML输入
In my opinion, a sensible input includes actual values for d
elements: 我认为,明智的输入包括d
元素的实际值:
<?xml version="1.0" encoding="UTF-8"?>
<a>
<b>
<c day="20150221">
<d>data from day 20150221</d>
<e>...</e>
</c>
<c day="20150222">
<d>data from day 20150222</d>
<e>...</e>
</c>
<c day="20150223">
<d>data from day 20150223</d>
<e>...</e>
</c>
</b>
<b>
<c day="20150219">
<d>data from day 20150219</d>
<e>...</e>
</c>
<c day="20150221">
<d>data from day 20150221</d>
<e>...</e>
</c>
<c day="20150223">
<d>data from day 20150223</d>
<e>...</e>
</c>
</b>
<!--...-->
</a>
Stylesheet 样式表
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output method="html" doctype-public="XSLT-compat" omit-xml-declaration="yes" encoding="UTF-8" indent="yes" />
<xsl:key name="day-from-c" match="c" use="@day" />
<xsl:template match="/">
<hmtl>
<xsl:apply-templates/>
</hmtl>
</xsl:template>
<xsl:template match="a">
<table>
<xsl:variable name="days" select="b/c[generate-id() =
generate-id(key('day-from-c', @day)[1])]"/>
<xsl:for-each select="$days">
<xsl:sort select="@day"/>
<th>
<xsl:value-of select="@day"/>
</th>
</xsl:for-each>
<tr>
<xsl:for-each select="$days">
<xsl:sort select="@day"/>
<td>
<xsl:value-of select="/a/b/c[@day = current()/@day]/d"/>
</td>
</xsl:for-each>
</tr>
</table>
</xsl:template>
</xsl:transform>
HTML Output HTML输出
It is still not clear to me what should happen if there are multiple d
elements on the same day. 我仍然不清楚如果同一天有多个d
元素会发生什么。
<!DOCTYPE html
PUBLIC "XSLT-compat">
<hmtl>
<table>
<th>20150219</th>
<th>20150221</th>
<th>20150222</th>
<th>20150223</th>
<tr>
<td>data from day 20150219</td>
<td>data from day 20150221 data from day 20150221</td>
<td>data from day 20150222</td>
<td>data from day 20150223 data from day 20150223</td>
</tr>
</table>
</hmtl>
Try this solution online on xsltransform . 在xsltransform上在线尝试此解决方案。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.