使用XSL循环XML文件并填充数据列

时间:2017-10-24 20:13:29

标签: xml xslt-1.0

以下是XML的简化摘录:

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="Workbook-S-140-PublicTalk-WatchtowerStudy-ServiceTalk.xsl"?>
<MeetingWorkBook>
    <Meeting BookmarkId="0" PageBreak="0" NumberClasses="1" SpecialEvent="0">
        <Date ThisWeek="W20171106" NextWeek="W20171113">November 6-12</Date>
        <MeetingDate Day="9" DayShort="Thu" DayFull="Thursday" Month="11" MonthShort="Nov" MonthFull="November" Year="2017"/>
    </Meeting>
    <Meeting BookmarkId="1" PageBreak="0" NumberClasses="1" SpecialEvent="0">
        <Date ThisWeek="W20171113" NextWeek="W20171120">November 13-19</Date>
        <MeetingDate Day="16" DayShort="Thu" DayFull="Thursday" Month="11" MonthShort="Nov" MonthFull="November" Year="2017"/>
    </Meeting>
    <Meeting BookmarkId="2" PageBreak="0" NumberClasses="1" SpecialEvent="0">
        <Date ThisWeek="W20171120" NextWeek="W20171127">November 20-26</Date>
        <MeetingDate Day="23" DayShort="Thu" DayFull="Thursday" Month="11" MonthShort="Nov" MonthFull="November" Year="2017"/>
    </Meeting>
    <Meeting BookmarkId="3" PageBreak="0" NumberClasses="1" SpecialEvent="0">
        <Date ThisWeek="W20171127" NextWeek="W20171204">November 27–December 3</Date>
        <MeetingDate Day="30" DayShort="Thu" DayFull="Thursday" Month="11" MonthShort="Nov" MonthFull="November" Year="2017"/>
    </Meeting>
</MeetingWorkBook>

这是一些提取的XSL脚本:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml">
  <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:template match="/">
    <html xmlns="http://www.w3.org/1999/xhtml">
      <xsl:attribute name="lang">
        <xsl:value-of select="//Settings//LanguageCode"/>
      </xsl:attribute>
      <xsl:attribute name="dir">
        <xsl:value-of select="//Settings/Direction"/>
      </xsl:attribute>
      <head>
        <meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
        <link rel="stylesheet" type="text/css" href="Workbook-S-140-PublicTalk-WatchtowerStudy-ServiceTalk.css"/>
        <title>
          <xsl:value-of select="//Labels/Congregation"/>&#160;<xsl:value-of select="//Labels/Title" />
        </title>
      </head>
      <body>
        <div class="containerPage">
          <xsl:for-each select="MeetingWorkBook/Meeting">
          </xsl:for-each>
        </div>
      </body>
    </html>
  </xsl:template>
</xsl:stylesheet>

现在,到目前为止,我总是每周处理一次,使用for循环。我基本上创建了第一周的数据表,然后是第二周的数据表,依此类推。

现在,我的一位用户问我是否可以使用XSL脚本以更精简的方式准备我的数据。例如:

New Report

如您所见,他希望每周使用一列表格。我不知道我怎么能这样做。当我创建表格和每一行(每行是一个赋值)时,我需要填写单元格,列表中每周一个。

我认为我对这个问题的解释过于复杂。

我可以用XSL以任何方式导航我的XML以实现他的愿望(不改变XML文件的语法)吗?

更新

我试过这个,我甚至不确定这是否是接近它的最佳方法:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml">
  <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:template match="/">
    <html xmlns="http://www.w3.org/1999/xhtml">
      <xsl:attribute name="lang">
        <xsl:value-of select="//Settings//LanguageCode"/>
      </xsl:attribute>
      <xsl:attribute name="dir">
        <xsl:value-of select="//Settings/Direction"/>
      </xsl:attribute>
      <head>
        <meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
        <link rel="stylesheet" type="text/css" href="Workbook-S-140-PublicTalk-WatchtowerStudy-ServiceTalk.css"/>
        <title>
          <xsl:value-of select="//Labels/Congregation"/>&#160;<xsl:value-of select="//Labels/Title" />
        </title>
      </head>
      <body>
        <table>
          <!--Date-->
          <tr>
            <td>
              <xsl:value-of  select="MeetingWorkBook/Meeting[1]/Date" />
            </td>
            <td>
              <xsl:value-of  select="MeetingWorkBook/Meeting[2]/Date" />
            </td>
            <td>
              <xsl:value-of  select="MeetingWorkBook/Meeting[3]/Date" />
            </td>
            <td>
              <xsl:value-of  select="MeetingWorkBook/Meeting[4]/Date" />
            </td>
            <!--But there might be a 5th element - How to check?-->
          </tr>
          <!--Process next row-->
        </table>
      </body>
    </html>
  </xsl:template>
</xsl:stylesheet>

Results

正如您所看到的那样有效,但我需要根据列表中的项目数有条件地处理第5列。不知道该怎么做。

此外,我发现这有很多重复的代码。

我再次尝试使用xsl:for-each。我以为我可以通过mode。我想那会很棒然后我会知道我想要展示什么。但无法通过mode

我是否朝着正确的方向前进,如何使其更加模块化?

更新2

我尝试使用count命令,但我做错了:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml">
  <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:template match="/">
    <html xmlns="http://www.w3.org/1999/xhtml">
      <xsl:attribute name="lang">
        <xsl:value-of select="//Settings//LanguageCode"/>
      </xsl:attribute>
      <xsl:attribute name="dir">
        <xsl:value-of select="//Settings/Direction"/>
      </xsl:attribute>
      <head>
        <meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
        <link rel="stylesheet" type="text/css" href="Workbook-S-140-PublicTalk-WatchtowerStudy-ServiceTalk.css"/>
        <title>
          <xsl:value-of select="//Labels/Congregation"/>&#160;<xsl:value-of select="//Labels/Title" />
        </title>
      </head>
      <body>
        <table>
          <!--Date-->
          <tr>
            <xsl:if test="MeetingWorkBook/Meeting[count(*) &gt;= 1]">
              <td>
                <xsl:value-of  select="MeetingWorkBook/Meeting[1]/Date" />
              </td>
            </xsl:if>
            <xsl:if test="MeetingWorkBook/Meeting[count(*) &gt;= 2]">
              <td>
                <xsl:value-of  select="MeetingWorkBook/Meeting[2]/Date" />
              </td>
            </xsl:if>
            <xsl:if test="MeetingWorkBook/Meeting[count(*) &gt;= 3]">
              <td>
                <xsl:value-of  select="MeetingWorkBook/Meeting[3]/Date" />
              </td>
            </xsl:if>
            <xsl:if test="MeetingWorkBook/Meeting[count(*) &gt;= 4]">
              <td>
                <xsl:value-of  select="MeetingWorkBook/Meeting[4]/Date" />
              </td>
            </xsl:if>
            <xsl:if test="MeetingWorkBook/Meeting[count(*) &gt;= 5]">
              <td>
                <xsl:value-of  select="MeetingWorkBook/Meeting[5]/Date" />
              </td>
            </xsl:if>
          </tr>
          <!--Process next row-->
        </table>
      </body>
    </html>
  </xsl:template>
</xsl:stylesheet>

更新3

好的,我已经弄清楚如何正确使用count功能:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml">
  <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:template match="/">
    <html xmlns="http://www.w3.org/1999/xhtml">
      <xsl:attribute name="lang">
        <xsl:value-of select="//Settings//LanguageCode"/>
      </xsl:attribute>
      <xsl:attribute name="dir">
        <xsl:value-of select="//Settings/Direction"/>
      </xsl:attribute>
      <head>
        <meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
        <link rel="stylesheet" type="text/css" href="Workbook-S-140-PublicTalk-WatchtowerStudy-ServiceTalk.css"/>
        <title>
          <xsl:value-of select="//Labels/Congregation"/>&#160;<xsl:value-of select="//Labels/Title" />
        </title>
      </head>
      <body>
        <table>
          <!--Date-->
          <tr>
            <xsl:if test="count(MeetingWorkBook/Meeting) &gt;= 1">
              <td>
                <xsl:value-of  select="MeetingWorkBook/Meeting[1]/Date" />
              </td>
            </xsl:if>
            <xsl:if test="count(MeetingWorkBook/Meeting) &gt;= 2">
              <td>
                <xsl:value-of  select="MeetingWorkBook/Meeting[2]/Date" />
              </td>
            </xsl:if>
            <xsl:if test="count(MeetingWorkBook/Meeting) &gt;= 3">
              <td>
                <xsl:value-of  select="MeetingWorkBook/Meeting[3]/Date" />
              </td>
            </xsl:if>
            <xsl:if test="count(MeetingWorkBook/Meeting) &gt;= 4">
              <td>
                <xsl:value-of  select="MeetingWorkBook/Meeting[4]/Date" />
              </td>
            </xsl:if>
            <xsl:if test="count(MeetingWorkBook/Meeting) &gt;= 5">
              <td>
                <xsl:value-of  select="MeetingWorkBook/Meeting[5]/Date" />
              </td>
            </xsl:if>
          </tr>
          <!--Process next row-->
        </table>
      </body>
    </html>
  </xsl:template>
</xsl:stylesheet>

所以,问题仍然存在,这是最有效的方法吗?我将不得不重复类似的代码,每行最多5个单元格。每行都要求我访问meeting节点中的某些信息。在第一行中,我访问了日期。但在下一行中,我将访问Chairman值。

我可以简化这一点,以便我只需要使用模板为每一位信息输入代码吗?

我在这里有意义。在添加所有其余脚本之前,我只想让逻辑简单有效。

感谢您的帮助。

1 个答案:

答案 0 :(得分:1)

这可能对您更有效。注意我在模板匹配中使用了*。因此,您可以使用相同的模板创建下一行。但是,您也可以指定日期并为下一行创建不同的模板。

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml">
  <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:template match="/">
    <html xmlns="http://www.w3.org/1999/xhtml">
      <xsl:attribute name="lang">
        <xsl:value-of select="//Settings//LanguageCode"/>
      </xsl:attribute>
      <xsl:attribute name="dir">
        <xsl:value-of select="//Settings/Direction"/>
      </xsl:attribute>
      <head>
        <meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
        <link rel="stylesheet" type="text/css" href="Workbook-S-140-PublicTalk-WatchtowerStudy-ServiceTalk.css"/>
        <title>
          <xsl:value-of select="//Labels/Congregation"/>&#160;<xsl:value-of select="//Labels/Title" />
        </title>
      </head>
      <body>
        <table>
          <!--Date-->
          <tr>
            <xsl:apply-templates select="MeetingWorkBook/Meeting/Date"/>
          </tr>
        </table>
      </body>
    </html>
  </xsl:template>

  <!-- column mode-->
  <xsl:template match="*">
    <td>
      <xsl:value-of  select="." />
    </td>
  </xsl:template>

</xsl:stylesheet>