我是CSS新手,遇到了障碍。我有一个图像详细信息列表,如下所示。
<Files IsList="true">
<Item>
<FileSize>97 kb</FileSize>
<Type>image/jpeg</Type>
<Name>CR_0_Pc_7vxsysv.jpg</Name>
<Description>Picture</Description>
</Item>
<Item>
<FileSize>108 kb</FileSize>
<Type>image/jpeg</Type>
<Name>CR_0_Pc_9cxjbh7.jpg</Name>
<Description>Picture</Description>
</Item>
<Item>
<FileSize>109 kb</FileSize>
<Type>image/jpeg</Type>
<Name>CR_0_Pc_9cxjbh7_Annotated.jpg</Name>
<Description>(annotated)</Description>
</Item>
<Item>
<FileSize>170 kb</FileSize>
<Type>image/jpeg</Type>
<Name>CR_0_Pc_omau6bn.jpg</Name>
<Description>Picture</Description>
</Item>
<Item>
<FileSize>175 kb</FileSize>
<Type>image/jpeg</Type>
<Name>CR_0_Pc_omau6bn_Annotated.jpg</Name>
<Description>(annotated)</Description>
</Item>
</Files>
所有图像都有一个原始文件,一些图像有一个带注释的副本(由描述和名称后缀标识)。
我需要显示所有图像(在一张包含3张图像的表中),逻辑:
Desired Outcome是一个选择语句,产生以下结果。
<Item>
<FileSize>97 kb</FileSize>
<Type>image/jpeg</Type>
<Name>CR_0_Pc_7vxsysv.jpg</Name>
<Description>Picture</Description>
</Item>
<Item>
<FileSize>109 kb</FileSize>
<Type>image/jpeg</Type>
<Name>CR_0_Pc_9cxjbh7_Annotated.jpg</Name>
<Description>(annotated)</Description>
</Item>
<Item>
<FileSize>175 kb</FileSize>
<Type>image/jpeg</Type>
<Name>CR_0_Pc_omau6bn_Annotated.jpg</Name>
<Description>(annotated)</Description>
</Item>
我试图循环遍历所有节点并使用IF语句来确定显示的是哪个,但是因为我使用position()来确定从哪一个开始新行,这不起作用,因为并非所有图像都显示,抛掉行计算。
我认为select需要基于Name元素值的子字符串,并与其他Name元素的子字符串进行比较。
这可能吗?
答案 0 :(得分:0)
我不知道你是否想要XSLT 1.0或XSLT 2.0,并且你不想要一个html表输出或xml输出(你似乎在这方面自相矛盾),所以这可能不完全符合您的要求,但可能会有所帮助。
这个XSLT 2.0样式表......
<xsl:transform
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="2.0">
<xsl:output method="html" version="5" encoding="UTF-8" indent="yes" />
<xsl:strip-space elements="*" />
<xsl:template match="/">
<hmtl>
<head>
<title>Table of items</title>
</head>
<body>
<table>
<tbody>
<xsl:for-each-group
select="Files/Item[
(Description eq '(annotated)') or
not(
for $name in concat( substring-before( Name/text(), '.jpg'), '_Annotated.jpg') return
following-sibling::Item[ Name eq $name])]"
group-by="(position() - 1) idiv 3">
<tr>
<xsl:apply-templates select="current-group()" />
</tr>
</xsl:for-each-group>
</tbody>
</table>
</body>
</hmtl>
</xsl:template>
<xsl:template match="Item">
<td>
<xsl:copy-of select="." />
</td>
</xsl:template>
</xsl:transform>
...将转换此输入文档......
<Files IsList="true">
<Item>
<FileSize>97 kb</FileSize>
<Type>image/jpeg</Type>
<Name>CR_0_Pc_7vxsysv.jpg</Name>
<Description>Picture</Description>
</Item>
<Item>
<FileSize>108 kb</FileSize>
<Type>image/jpeg</Type>
<Name>CR_0_Pc_9cxjbh7.jpg</Name>
<Description>Picture</Description>
</Item>
<Item>
<FileSize>109 kb</FileSize>
<Type>image/jpeg</Type>
<Name>CR_0_Pc_9cxjbh7_Annotated.jpg</Name>
<Description>(annotated)</Description>
</Item>
<Item>
<FileSize>170 kb</FileSize>
<Type>image/jpeg</Type>
<Name>CR_0_Pc_omau6bn.jpg</Name>
<Description>Picture</Description>
</Item>
<Item>
<FileSize>175 kb</FileSize>
<Type>image/jpeg</Type>
<Name>CR_0_Pc_omau6bn_Annotated.jpg</Name>
<Description>(annotated)</Description>
</Item>
</Files>
...进入此输出html页面......
<!DOCTYPE HTML>
<hmtl>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Table of items</title>
</head>
<body>
<table>
<tbody>
<tr>
<td>
<Item>
<FileSize>97 kb</FileSize>
<Type>image/jpeg</Type>
<Name>CR_0_Pc_7vxsysv.jpg</Name>
<Description>Picture</Description>
</Item>
</td>
<td>
<Item>
<FileSize>109 kb</FileSize>
<Type>image/jpeg</Type>
<Name>CR_0_Pc_9cxjbh7_Annotated.jpg</Name>
<Description>(annotated)</Description>
</Item>
</td>
<td>
<Item>
<FileSize>175 kb</FileSize>
<Type>image/jpeg</Type>
<Name>CR_0_Pc_omau6bn_Annotated.jpg</Name>
<Description>(annotated)</Description>
</Item>
</td>
</tr>
</tbody>
</table>
</body>
</hmtl>
分组(xsl:for-each-group
)实际上只是将输出编组到3列表中。桌子将是粗糙的。如果您需要常规表来支持旧版浏览器,则需要在最后一行添加一些额外代码。
以下是您在关闭</tr>
之前添加的内容,以使其成为常规
<xsl:for-each select="1 to 3 - count(current-group())">
<td> </td>
</xsl:for-each>
xsl:for-each-group/@select
中的XPath表达式为此解决方案带来了沉重的负担。它选择所有注释的Item
元素或没有匹配的带注释的兄弟元素。这基本上是您要处理输出的内容。
这是一个等效的XSLT 1.0解决方案..
<xsl:transform
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common"
extension-element-prefixes="exsl"
version="1.0">
<xsl:output method="html" doctype-system="" encoding="UTF-8" indent="yes" />
<xsl:strip-space elements="*" />
<xsl:template match="/">
<hmtl>
<head>
<title>Table of items</title>
</head>
<body>
<table>
<tbody>
<xsl:variable name="Items">
<xsl:apply-templates select="Files/Item" mode="filter-items" />
</xsl:variable>
<xsl:apply-templates select="exsl:node-set($Items)/Item" mode="row" />
</tbody>
</table>
</body>
</hmtl>
</xsl:template>
<xsl:template match="Item[Description='(annotated)']" mode="filter-items">
<xsl:copy-of select="." />
</xsl:template>
<xsl:template match="Item[Description!='(annotated)']" mode="filter-items">
<xsl:variable name="name" select="concat( substring-before( Name/text(), '.jpg'), '_Annotated.jpg')" />
<xsl:if test="not( following-sibling::Item[ Name = $name])">
<xsl:copy-of select="." />
</xsl:if>
</xsl:template>
<xsl:template match="Item[1]" mode="row">
<tr>
<xsl:apply-templates select=". | following-sibling::Item[position() <= 2]" mode="cell" />
<xsl:variable name="empty-cols" select=" 3 - count(. | following-sibling::Item[position() <= 2])" />
<xsl:for-each select="(//node())[position() <= $empty-cols]">
<td> </td>
</xsl:for-each>
</tr>
</xsl:template>
<xsl:template match="Item" mode="row" />
<xsl:template match="Item" mode="cell">
<td>
<xsl:copy-of select="." />
</td>
</xsl:template>
</xsl:transform>
以上假设您的XSLT 1.0引擎支持exslt。请注意,没有理由不升级到XSLT 2.0。如果您的平台是浏览器,那么您可以使用Saxon CE来实现升级。输出表与the Piez method保持一致。如果效率太低,还有其他选择。
答案 1 :(得分:0)
- 如果有带注释的副本,则仅显示带注释的版本
- 如果没有带注释的副本,则显示原件。
Desired Outcome是一个选择语句,产生以下结果。
您可以使用以下表达式选择所需的项目:
select="Item[Description='(annotated)' or not(key('anno', substring(Name, 1, 15)))]"/>
定义一个键之后:
<xsl:key name="anno" match="Item[Description='(annotated)']" use="substring(Name, 1, 15)" />
这假定所有项目名称长度恰好为15个字符。如果这个假设不正确,那就会变得更复杂。
请注意,仅选择项目是不够的,因为所选项目保持其原始上下文。为了使所选项目成为兄弟姐妹,您需要将它们复制到变量中。以下是完整样式表的示例,将所选项目分为三列:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common"
extension-element-prefixes="exsl">
<xsl:output method="html" encoding="utf-8"/>
<xsl:key name="anno" match="Item[Description='(annotated)']" use="substring(Name, 1, 15)" />
<xsl:template match="/Files">
<xsl:variable name="items">
<xsl:copy-of select="Item[Description='(annotated)' or not(key('anno', substring(Name, 1, 15)))]"/>
</xsl:variable>
<xsl:variable name="cols" select="3" />
<table border="1">
<xsl:for-each select="exsl:node-set($items)/Item[position() mod $cols = 1]" >
<tr>
<xsl:apply-templates select=". | following-sibling::Item[position() < $cols]"/>
</tr>
</xsl:for-each>
</table>
</xsl:template>
<xsl:template match="Item">
<td><img src="{Name}"/></td>
</xsl:template>
</xsl:stylesheet>