在xslt中选择多个元素

时间:2014-05-19 20:25:53

标签: c# html xml xslt

我是XSLT的新手。我有一个问题和一个问题。 问题: 我有一个类似于:

的xml
<data>
  <element>
     <Title>Title1</Title>
     <Author>Author1</Author>
  </element>
  <element>
     <Title>Title2</Title>
     <Author>Author2</Author>
  </element>
  <element>
     <Title>Title3</Title>
     <Author>Author3</Author>
  </element>
  <element>
     <Title>Title4</Title>
     <Author>Author4</Author>
  </element>
  (...)
</data>

我想得到一个类似于:

的结构
<table>
      <tr>
        <td style="padding:2px 0px 5px 0px;">
           Title1 Author1
           Title2 Author2
        </td>
      </tr>
      <tr>
        <td style="padding:2px 0px 5px 0px;">
           Title3 Author3
           Title4 Author4
        </td>
      </tr>
     (...)
</table>

请注意,作者1,2被分组在一起,类似于3和4.它们是根据位置分组的(而不是Author1我当然会有一个名字,所以我无法从内部提取数字xml)。 位置1与位置2 位置3与位置4 ...

我在xslt中尝试过类似的东西:

<xsl:for-each select="element">
      <xsl:if test="(position() mod 2 = 0)">
        <tr>    <------ THIS APPEARS AS NOT CLOSED
          <td style="padding:2px 0px 5px 0px;">    <------ THIS APPEARS AS NOT CLOSED
            <xsl:call-template name="content"/>
      </xsl:if>
      <xsl:if test="(position() mod 2 = 1)">
        <xsl:call-template name="content"/>
        </td> <------ THIS WOULD BE THE CLOSED TD
        </tr> <------ THIS WOULD BE THE CLOSED TR
      </xsl:if>
    </xsl:for-each>
  </xsl:template>

<xsl:call-template name="content"/>只是为我提取所需信息,没有任何花哨,仅xsl:value-of select

问题:

  1. 如何生成打开和关闭的<td><tr>?上面的xslt确实编译,因为看起来tdtr可能仍然是未闭合的,这似乎是非法的。
  2. 我听说xslt中的for-each是一个糟糕的模式。这是真的吗?如果是的话,会推荐什么?
  3. 我在C#中使用XslCompiledTransform,因此xslt 2应该可以工作。

2 个答案:

答案 0 :(得分:2)

尝试:

XSLT 1.0

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

<xsl:template match="/data">
    <table>
        <xsl:for-each select="element[position() mod 2 = 1]">
            <tr>
                <td>
                    <xsl:value-of select="Title"/>
                    <xsl:text> </xsl:text>
                    <xsl:value-of select="Author"/>
                    <br/>
                    <xsl:value-of select="following-sibling::element[1]/Title"/>
                    <xsl:text> </xsl:text>
                    <xsl:value-of select="following-sibling::element[1]/Author"/>
                </td>
            </tr>
        </xsl:for-each>
    </table>
</xsl:template>

</xsl:stylesheet>

答案 1 :(得分:0)

这个XSLT应该让你入门。我添加了空格,但如果它们无关紧要,您只需删除<xsl:text>元素:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

    <xsl:output indent="yes"/>

    <xsl:template match="data">
        <table>
            <xsl:apply-templates select="element[(position()+1) mod 2 = 0]"/>
        </table>
    </xsl:template>

    <xsl:template match="element">
        <tr>
            <td style="padding:2px 0px 5px 0px;">
                <xsl:text>&#xa;         </xsl:text>
                <xsl:apply-templates select="*"/>
                <xsl:text>&#xa;         </xsl:text>
                <xsl:apply-templates select="following-sibling::element[1]/*"/>
                <xsl:text>&#xa;      </xsl:text>
            </td>
        </tr>
    </xsl:template>

    <xsl:template match="Title">
        <xsl:value-of select="."/>
        <xsl:text> </xsl:text>
    </xsl:template>

    <xsl:template match="Author">
        <xsl:value-of select="."/>
    </xsl:template>

</xsl:stylesheet>

您不需要任何for-blocks或复杂嵌套,因为每个模板都是递归处理的,因此每个节点都会处理相同的模板。