使用 XML 文件中的链接和应用模板改进了 XSL 脚本
Improved XSL script with a linked in XML file and applying templates
这是一些 XSL 脚本:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msa="http://www.publictalksoftware.co.uk/msa">
<xsl:output method="html" indent="yes" version="4.01"
doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
doctype-public="//W3C//DTD XHTML 1.0 Transitional//EN"/>
<xsl:variable name="DutyHistory" select="document('DutyAssignHistory.XML')"/>
<xsl:template match="/">
<html>
<head>
<title>Test</title>
</head>
<body>
<xsl:for-each select="MeetingWorkBook/Meeting">
<p>
<xsl:value-of select ="Date/@ThisWeek"/>
</p>
<xsl:variable name="Week" select="Date/@ThisWeek"/>
<table>
<tr>
<td>Sound</td>
<td>
<xsl:value-of select="$DutyHistory/msa:DutyAssignmentHistory/msa:DutyAssignments/msa:DutyAssignmentEntry[@Week=$Week and @Mode='Weekend']/msa:Assignment[@Index='1' and @IndexType='Fixed']"/>
</td>
</tr>
<tr>
<td>Platform</td>
<td>
<xsl:value-of select="$DutyHistory/msa:DutyAssignmentHistory/msa:DutyAssignments/msa:DutyAssignmentEntry[@Week=$Week and @Mode='Weekend']/msa:Assignment[@Index='5' and @IndexType='Fixed']"/>
</td>
</tr>
<tr>
<td>Left Mike</td>
<td>
<xsl:value-of select="$DutyHistory/msa:DutyAssignmentHistory/msa:DutyAssignments/msa:DutyAssignmentEntry[@Week=$Week and @Mode='Weekend']/msa:Assignment[@Index='7' and @IndexType='Fixed']"/>
</td>
</tr>
<tr>
<td>Right Mike</td>
<td>
<xsl:value-of select="$DutyHistory/msa:DutyAssignmentHistory/msa:DutyAssignments/msa:DutyAssignmentEntry[@Week=$Week and @Mode='Weekend']/msa:Assignment[@Index='8' and @IndexType='Fixed']"/>
</td>
</tr>
<tr>
<td>Public Talk Chairman</td>
<td>
<xsl:value-of select="$DutyHistory/msa:DutyAssignmentHistory/msa:DutyAssignments/msa:DutyAssignmentEntry[@Week=$Week and @Mode='Weekend']/msa:Assignment[@Index='4' and @IndexType='Custom']"/>
</td>
</tr>
<tr>
<td>Watchtower Reader</td>
<td>
<xsl:value-of select="$DutyHistory/msa:DutyAssignmentHistory/msa:DutyAssignments/msa:DutyAssignmentEntry[@Week=$Week and @Mode='Weekend']/msa:Assignment[@Index='5' and @IndexType='Custom']"/>
</td>
</tr>
</table>
</xsl:for-each>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
如您所见,它链接到另一个 XML 文档以供参考。这是文件中链接的一个示例:
<?xml version="1.0" encoding="utf-8"?>
<DutyAssignmentHistory xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.publictalksoftware.co.uk/msa">
<DutyAssignments>
<DutyAssignmentEntry Date="2018-01-04" Week="W20180101" Template="0" Mode="Midweek">
<Assignment Index="2" IndexType="Fixed">Name 1</Assignment>
<Assignment Index="5" IndexType="Fixed">Name 2</Assignment>
<Assignment Index="7" IndexType="Fixed">Name 3</Assignment>
<Assignment Index="8" IndexType="Fixed">Name 4</Assignment>
<Assignment Index="13" IndexType="Fixed">Name 5</Assignment>
<Assignment Index="14" IndexType="Fixed">Name 6</Assignment>
</DutyAssignmentEntry>
</DutyAssignments>
</DutyAssignmentHistory>
用户可能希望参考 XML 中的信息并按他们喜欢的方式显示,但我想向他们展示最简单的方法。
如您所见,有几个条件:
Week
(WYYYYMMDD)
Mode
(Midweek
、Weekend
或 Weekly
)
Template
(0 或更高)
以上将过滤到右侧 周 的作业。然后,确定实际分配:
Index
(数值)
IndexType
(Fixed
、CustomFixed
或 Custom
)
我能否以任何方式使用模板(可能使用变量)来简化重复的代码?
您可以使用模板并传递参数,或者在 XSLT 2.0 或更高版本中,您还可以定义一个函数,这使得它更易于使用并节省了一些输入。但是对于你目前所做的事情,一个变量和一些谓词过滤器似乎是最简单易行的。
最简单易行的方法是将一个变量与周末分配绑定,然后将谓词过滤器应用于 select 具有 @Index
和 @IndexType
的变量:
<xsl:variable name="Week" select="Date/@ThisWeek"/>
<xsl:variable name="weekend-assignments"
select="$DutyHistory/msa:DutyAssignmentHistory/msa:DutyAssignments
/msa:DutyAssignmentEntry[@Week=$Week and @Mode='Weekend']/msa:Assignment"/>
<table>
<tr>
<td>Sound</td>
<td>
<xsl:value-of select="$weekend-assignments[@Index='1' and @IndexType='Fixed']"/>
</td>
</tr>
如果让变量包含一组未过滤的 Assignment
元素,则可以在谓词中执行所有过滤:
<xsl:variable name="Week" select="Date/@ThisWeek"/>
<xsl:variable name="assignments"
select="$DutyHistory/msa:DutyAssignmentHistory/msa:DutyAssignments
/msa:DutyAssignmentEntry/msa:Assignment"/>
<table>
<tr>
<td>Sound</td>
<td>
<xsl:value-of
select="$assignments[@Index='1' and @IndexType='Fixed']
[..[@Week=$Week and @Mode='Weekend' and @Template='0']]"/>
</td>
</tr>
如果要合并生成列的逻辑,可以为 msa:Assignment
定义一个模板:
<xsl:template match="msa:Assignment">
<td>
<xsl:value-of select="."/>
</td>
</xsl:template>
然后像这样使用它:
<table>
<tr>
<td>Sound</td>
<xsl:apply-templates select="$weekend-assignments[@Index='1' and @IndexType='Fixed']"/>
如果要合并生成行的逻辑,可以为msa:Assignment
定义一个模板并为第一列发送一个参数:
<xsl:template match="msa:Assignment">
<xsl:param name="label"/>
<tr>
<td><xsl:value-of select="$label"/></td>
<td>
<xsl:value-of select="."/>
</td>
</tr>
</xsl:template>
然后像这样使用它:
<table>
<xsl:apply-templates select="$weekend-assignments[@Index='1' and @IndexType='Fixed']">
<xsl:with-param name="label" select="'Sound'"/>
</xsl:apply-templates>
这是一些 XSL 脚本:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msa="http://www.publictalksoftware.co.uk/msa">
<xsl:output method="html" indent="yes" version="4.01"
doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
doctype-public="//W3C//DTD XHTML 1.0 Transitional//EN"/>
<xsl:variable name="DutyHistory" select="document('DutyAssignHistory.XML')"/>
<xsl:template match="/">
<html>
<head>
<title>Test</title>
</head>
<body>
<xsl:for-each select="MeetingWorkBook/Meeting">
<p>
<xsl:value-of select ="Date/@ThisWeek"/>
</p>
<xsl:variable name="Week" select="Date/@ThisWeek"/>
<table>
<tr>
<td>Sound</td>
<td>
<xsl:value-of select="$DutyHistory/msa:DutyAssignmentHistory/msa:DutyAssignments/msa:DutyAssignmentEntry[@Week=$Week and @Mode='Weekend']/msa:Assignment[@Index='1' and @IndexType='Fixed']"/>
</td>
</tr>
<tr>
<td>Platform</td>
<td>
<xsl:value-of select="$DutyHistory/msa:DutyAssignmentHistory/msa:DutyAssignments/msa:DutyAssignmentEntry[@Week=$Week and @Mode='Weekend']/msa:Assignment[@Index='5' and @IndexType='Fixed']"/>
</td>
</tr>
<tr>
<td>Left Mike</td>
<td>
<xsl:value-of select="$DutyHistory/msa:DutyAssignmentHistory/msa:DutyAssignments/msa:DutyAssignmentEntry[@Week=$Week and @Mode='Weekend']/msa:Assignment[@Index='7' and @IndexType='Fixed']"/>
</td>
</tr>
<tr>
<td>Right Mike</td>
<td>
<xsl:value-of select="$DutyHistory/msa:DutyAssignmentHistory/msa:DutyAssignments/msa:DutyAssignmentEntry[@Week=$Week and @Mode='Weekend']/msa:Assignment[@Index='8' and @IndexType='Fixed']"/>
</td>
</tr>
<tr>
<td>Public Talk Chairman</td>
<td>
<xsl:value-of select="$DutyHistory/msa:DutyAssignmentHistory/msa:DutyAssignments/msa:DutyAssignmentEntry[@Week=$Week and @Mode='Weekend']/msa:Assignment[@Index='4' and @IndexType='Custom']"/>
</td>
</tr>
<tr>
<td>Watchtower Reader</td>
<td>
<xsl:value-of select="$DutyHistory/msa:DutyAssignmentHistory/msa:DutyAssignments/msa:DutyAssignmentEntry[@Week=$Week and @Mode='Weekend']/msa:Assignment[@Index='5' and @IndexType='Custom']"/>
</td>
</tr>
</table>
</xsl:for-each>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
如您所见,它链接到另一个 XML 文档以供参考。这是文件中链接的一个示例:
<?xml version="1.0" encoding="utf-8"?>
<DutyAssignmentHistory xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.publictalksoftware.co.uk/msa">
<DutyAssignments>
<DutyAssignmentEntry Date="2018-01-04" Week="W20180101" Template="0" Mode="Midweek">
<Assignment Index="2" IndexType="Fixed">Name 1</Assignment>
<Assignment Index="5" IndexType="Fixed">Name 2</Assignment>
<Assignment Index="7" IndexType="Fixed">Name 3</Assignment>
<Assignment Index="8" IndexType="Fixed">Name 4</Assignment>
<Assignment Index="13" IndexType="Fixed">Name 5</Assignment>
<Assignment Index="14" IndexType="Fixed">Name 6</Assignment>
</DutyAssignmentEntry>
</DutyAssignments>
</DutyAssignmentHistory>
用户可能希望参考 XML 中的信息并按他们喜欢的方式显示,但我想向他们展示最简单的方法。
如您所见,有几个条件:
Week
(WYYYYMMDD)Mode
(Midweek
、Weekend
或Weekly
)Template
(0 或更高)
以上将过滤到右侧 周 的作业。然后,确定实际分配:
Index
(数值)IndexType
(Fixed
、CustomFixed
或Custom
)
我能否以任何方式使用模板(可能使用变量)来简化重复的代码?
您可以使用模板并传递参数,或者在 XSLT 2.0 或更高版本中,您还可以定义一个函数,这使得它更易于使用并节省了一些输入。但是对于你目前所做的事情,一个变量和一些谓词过滤器似乎是最简单易行的。
最简单易行的方法是将一个变量与周末分配绑定,然后将谓词过滤器应用于 select 具有 @Index
和 @IndexType
的变量:
<xsl:variable name="Week" select="Date/@ThisWeek"/>
<xsl:variable name="weekend-assignments"
select="$DutyHistory/msa:DutyAssignmentHistory/msa:DutyAssignments
/msa:DutyAssignmentEntry[@Week=$Week and @Mode='Weekend']/msa:Assignment"/>
<table>
<tr>
<td>Sound</td>
<td>
<xsl:value-of select="$weekend-assignments[@Index='1' and @IndexType='Fixed']"/>
</td>
</tr>
如果让变量包含一组未过滤的 Assignment
元素,则可以在谓词中执行所有过滤:
<xsl:variable name="Week" select="Date/@ThisWeek"/>
<xsl:variable name="assignments"
select="$DutyHistory/msa:DutyAssignmentHistory/msa:DutyAssignments
/msa:DutyAssignmentEntry/msa:Assignment"/>
<table>
<tr>
<td>Sound</td>
<td>
<xsl:value-of
select="$assignments[@Index='1' and @IndexType='Fixed']
[..[@Week=$Week and @Mode='Weekend' and @Template='0']]"/>
</td>
</tr>
如果要合并生成列的逻辑,可以为 msa:Assignment
定义一个模板:
<xsl:template match="msa:Assignment">
<td>
<xsl:value-of select="."/>
</td>
</xsl:template>
然后像这样使用它:
<table>
<tr>
<td>Sound</td>
<xsl:apply-templates select="$weekend-assignments[@Index='1' and @IndexType='Fixed']"/>
如果要合并生成行的逻辑,可以为msa:Assignment
定义一个模板并为第一列发送一个参数:
<xsl:template match="msa:Assignment">
<xsl:param name="label"/>
<tr>
<td><xsl:value-of select="$label"/></td>
<td>
<xsl:value-of select="."/>
</td>
</tr>
</xsl:template>
然后像这样使用它:
<table>
<xsl:apply-templates select="$weekend-assignments[@Index='1' and @IndexType='Fixed']">
<xsl:with-param name="label" select="'Sound'"/>
</xsl:apply-templates>