带有嵌套表的XSLT中的数据对齐问题

时间:2018-07-13 17:28:59

标签: xml xslt ms-word

我正在使用XSLT和嵌套表通过FoundationPHP生成Word文档。

我想要的结果是:

Table 1        Table 2
Image 1        Image 2
Label 1        Label 2
Data 1         Data 2

Table 3        Table 4
Image 3        Image 4
Label 3        Label 4
Data 3         Data 4

Table 5
Image 5
Label 5
Data 5

但是,我得到的是:

Table 1        Table 2
Image 1        Image 2
Label 1        Label 2
Label 1        Label 4

Table 3        Table 4
Image 3        Image 4
Label 3        Label 4
Data 2        Label 5

Table 5
Image 5
Label 5
Data 3

我的XSLT代码(为发布目的而简化)

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:w="http://some.bla">      <!-- Namespace of 'w' added by edit -->
    <xsl:template match="/">
        <w:document>             <!-- Added by edit !!! -->
            blah
            <w:body>
                <w:tbl>
                    <xsl:variable name="size" select="count(root/row)"/>

                    <xsl:for-each name="count" select="root/row[ceiling($size div 2) &gt;= position()]">
                        <xsl:variable name="level0Count" select="position()"/>
                        <xsl:variable name="imageid" select="position()+1"/>
                        <xsl:variable name="level1Count" select="position() - 1"/>
                        <xsl:variable name="level2Count" select="$level1Count * 2 + position()"/>
                        <w:tr w:rsidR="003346C6" w:rsidTr="003346C6">
                            <w:tc>
                                <w:tcPr>
                                    <w:tcW w:w="4648" w:type="dxa"/>
                                </w:tcPr>
                                <w:tbl>
                                    <w:tr w:rsidR="003346C6" w:rsidTr="00BD1383">
                                        <w:tc>
                                            <w:p w:rsidR="003346C6" w:rsidRDefault="003346C6" w:rsidP="003346C6">
                                                <w:r>
                                                    Image 1
                                                </w:r>
                                            </w:p>
                                        </w:tc>
                                    </w:tr>
                                    <w:tr w:rsidR="003346C6" w:rsidTr="00BD1383">
                                        <w:tc>
                                            <w:p w:rsidR="003346C6" w:rsidRPr="0004412A" w:rsidRDefault="003346C6" w:rsidP="003346C6">
                                                <w:r w:rsidRPr="0004412A">
                                                    <xsl:choose>
                                                        <xsl:when test="position()=1">
                                                            <w:t>Label <xsl:value-of select="position()"/>
                                                                <w:b />
                                                            </w:t>
                                                        </xsl:when>
                                                        <xsl:otherwise>
                                                            <w:t>Label <xsl:value-of select="2*position()-1"/>
                                                                <w:b />
                                                            </w:t>
                                                        </xsl:otherwise>
                                                    </xsl:choose>
                                                </w:r>
                                            </w:p>
                                            <w:p w:rsidR="003346C6" w:rsidRPr="005F3377" w:rsidRDefault="003346C6" w:rsidP="003346C6">
                                                <w:r>
                                                    <w:t>
                                                        <xsl:value-of select="Data"/>
                                                    </w:t>
                                                </w:r>
                                                <w:bookmarkStart w:id="0" w:name="_GoBack"/>
                                                <w:bookmarkEnd w:id="0"/>
                                            </w:p>
                                        </w:tc>
                                    </w:tr>
                                </w:tbl>
                                <w:p w:rsidR="003346C6" w:rsidRDefault="003346C6" w:rsidP="003346C6"/>
                            </w:tc>
                            <xsl:if test="following::row[ceiling($size div 2)]/data!=''">
                                <w:tc>
                                    <w:tcPr>
                                        <w:tcW w:w="4648" w:type="dxa"/>
                                    </w:tcPr>
                                    <w:tbl>
                                        <w:tr w:rsidR="003346C6" w:rsidTr="00BD1383">
                                            <w:tc>
                                                <w:p w:rsidR="003346C6" w:rsidRDefault="003346C6" w:rsidP="003346C6">
                                                    <w:r>
                                                        Image 2
                                                    </w:r>
                                                </w:p>
                                            </w:tc>
                                        </w:tr>
                                        <w:tr w:rsidR="003346C6" w:rsidTr="00BD1383">
                                            <w:tc>
                                                <w:p w:rsidR="003346C6" w:rsidRDefault="003346C6" w:rsidP="003346C6">
                                                    <w:r>
                                                        <xsl:choose>
                                                            <xsl:when test="position()=1">
                                                                <w:t>
                                                                    Label <xsl:value-of select="position()+1"/>
                                                                </w:t>
                                                            </xsl:when>
                                                            <xsl:otherwise>
                                                                <xsl:if test="following::row[ceiling($size div 2)]/data!=''">
                                                                    <w:t>
                                                                        Label <xsl:value-of select="2*position()"/>
                                                                    </w:t>
                                                                </xsl:if>
                                                            </xsl:otherwise>
                                                        </xsl:choose>
                                                    </w:r>
                                                </w:p>
                                                <w:p w:rsidR="003346C6" w:rsidRPr="005F3377" w:rsidRDefault="003346C6" w:rsidP="003346C6">
                                                    <w:r>
                                                        <w:t>
                                                            <xsl:value-of select="following::row[ceiling($size div 2)]/data"/>
                                                        </w:t>
                                                    </w:r>
                                                </w:p>
                                            </w:tc>
                                        </w:tr>
                                    </w:tbl>
                                    <w:p w:rsidR="003346C6" w:rsidRDefault="003346C6" w:rsidP="003346C6"/>
                                </w:tc>

                            </xsl:if>
                        </w:tr>
                    </xsl:for-each>
                </w:tbl>
                <w:p w:rsidR="00A00BC9" w:rsidRDefault="00A00BC9"/>
            </w:body>
        </w:document>
    </xsl:template>
</xsl:stylesheet>

如您所见,图像和标签是正确的,但是数据是垂直输入的。我一直在盯着这段代码,以至于我的双重视野让我第二次猜测一切。

编辑:这是我脚本的XML输出。 (我只包含3行)

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <row>
        <id>10755</id>
        <image>10755/11786.jpg</image>
        <data> 8220 Southwest Warm Springs Street</data>
    </row>
    <row>
        <id>10493</id>
        <image>10493/11786.jpg</image>
        <data> 21101-21149 SW 115th Avenue</data>
    </row>
    <row>
        <id>11008</id>
        <image>11008/11786.jpg</image>
        <data> 7144 NW Progress Court</data>
    </row>
</root>

为使问题更完整,下面是获取数据的代码:

if ( isset( $_GET[ 'id' ] ) ) {
    $sql = "SELECT ID, data, image FROM property WHERE ID in (" . $_GET['id'] .") ORDER BY field(ID," . $_GET['id'] .")";
    $result = $db->query($sql);
    if ($db->error) {
        $error = $db->error;
    }
}
}

function getRow($result) {
    return $result->fetch_assoc();
}

2 个答案:

答案 0 :(得分:1)

如果目标是将row元素的序列(即第1、2、3、4、5行)映射到两列表,则每个表单元格都包含第a行的数据,并且布局为

<table>
  <row><cell>1</cell><cell>2</cell></row>
  <row><cell>3</cell><cell>4</cell></row>
  <row><cell>5</cell></row>
</table>

然后,我认为通过处理奇数行将它们映射到表行,然后通过处理该奇数行及其紧随其后的同级,然后在需要时将每行映射到嵌套,可以在每行中构建两个单元格,这很容易表,显示输入row元素的数据。

以下是使用HTML表作为目标格式的示例:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:exsl="http://exslt.org/common"
    xmlns:msxml="urn:schemas-microsoft-com:xslt"
    exclude-result-prefixes="exsl msxml"
    version="1.0">

  <xsl:output method="html" indent="yes" version="5" doctype-system="about:legacy-doctype"/>


  <xsl:template match="/">
    <html>
      <head>
        <title>.NET XSLT Fiddle Example</title>
      </head>
      <body>
          <xsl:apply-templates/>
      </body>
    </html>
  </xsl:template>

  <xsl:template match="root">
      <table>
          <thead>
              <tr>
                  <th>col 1</th>
                  <th>col 2</th>
              </tr>
          </thead>
          <tbody>
              <xsl:apply-templates select="row[position() mod 2 = 1]" mode="row"/>
          </tbody>
      </table>
  </xsl:template>

  <xsl:template match="row" mode="row">
      <tr>
          <xsl:apply-templates select=". | following-sibling::row[1]" mode="cell"/>
      </tr>
  </xsl:template>

  <xsl:template match="row" mode="cell">
      <td>
          <xsl:apply-templates select="." mode="table"/>
      </td>
  </xsl:template>

  <xsl:template match="row" mode="table">
      <table>
          <thead>
              <tr>
                  <th>Table <xsl:number/></th>
                  <xsl:apply-templates select="*" mode="th"/>
              </tr>
          </thead>
          <tbody>
              <tr>
                  <td><xsl:number/></td>
                  <xsl:apply-templates select="*"/>
              </tr>
          </tbody>
      </table>
  </xsl:template>

  <xsl:template match="row/*" mode="th">
      <th>
          <xsl:value-of select="local-name()"/>
      </th>
  </xsl:template>

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

  <xsl:template match="row/image">
      <td>
          Image <xsl:number count="row"/> <img src="{.}" alt="image"/>
      </td>
  </xsl:template>

</xsl:stylesheet>

https://xsltfiddle.liberty-development.net/6qVRKwi

当然,需要将结果元素调整为目标标记语言,但是算法应该相同,剩下的唯一问题是确保在有奇数的情况下将空单元格添加到最后一个表行中输入row元素中的所有元素,目标布局不起作用或缺少单元格看起来很糟糕。只需将一个模板更改为

,即可轻松完成此操作
  <xsl:template match="row" mode="row">
      <tr>
          <xsl:apply-templates select=". | following-sibling::row[1]" mode="cell"/>
          <xsl:if test="not(following-sibling::row)">
              <td></td>
          </xsl:if>
      </tr>
  </xsl:template>

https://xsltfiddle.liberty-development.net/6qVRKwi/1

中完成

答案 1 :(得分:1)

在您第一次调用数据时,将其更改为

<xsl:choose>
  <xsl:when test="position()=1">
    <w:t><xsl:value-of select="data"/></w:t>
  </xsl:when>
  <xsl:otherwise>
    <w:t><xsl:value-of select="following::row[$imageid - 2]/data"/></w:t>
  </xsl:otherwise>
</xsl:choose>

然后在第二个通话中使用

    <w:t><xsl:value-of select="following::row[$imageid - 1]/data"/></w:t>

这应该按照您想要的方式排列数据。