如何将每个第3个元素包装到div中,每个元素都包含xslt

时间:2014-01-14 22:55:33

标签: xml xslt

我是XSLT的新手。 这是我的XML

<contact>
 <person>
   <name>Hannah</name>
   <phone>123-123-123</phone>
   <address>No.1 A St. city</address>
 <person>

 <person>
   <name>David</name>
   <phone>223-223-223</phone>
   <address>No.2 B BRC. city</address>
 <person>

 <person>
   <name>Tim</name>
   <phone>323-223-333</phone>
   <address>No.3 c BRC. city</address>
 <person>

  <person>
   <name>May</name>
   <phone>443-443-443</phone>
   <address>No.4 bb Rd. city</address>
  <person>

  <person>
   <name>Rose</name>
   <phone>7743-443-443</phone>
   <address>No.7 rolling Rd. city</address>
  <person>

  ..........more
 <contact>

OUTPUT 我想要

<div class="group">
    <div class="info">
        <h2>Hannah<h2/>
        <h3>123-123-123</h3>
        <p>No.1 A St. city<p/>
    </div>

    <div class="info">
        <h2>David<h2/>
        <h3>223-223-223</h3>
        <p>No.2 B BRC. city<p/>
    </div>

    <div class="info">
        <h2>Tim<h2/>
        <h3>323-223-333</h3>
        <p>No.3 c BRC. city<p/>
    </div>
</div>

<div class="group">
    <div class="info">
        <h2>May</h2>
        <h3>443-443-443</h3>
        <p>No.4 bb Rd. city</p>
    </div>

    <div class="info">
        <h2>Rose</h2>
        <h3>7743-443-443</h3>
        <p>No.7 rolling Rd. city</p>
    </div>

 ..... Loop if has more 
</div>

这是我做的,但有很多错误。 如何选择更多for-each select

<xsl:template name="group">
    <xsl:param name="name"/>
    <xsl:param name="phone"/>
    <xsl:param name="address"/>
    <div class="info">
       <h2><xsl:value-of select="$name"/></h2>
       <h3><xsl:value-of select="$phone"/></h3>
       <p><xsl:value-of select="$address"/></p>
    </div>
</xsl:template>

  <xsl:template match="/*">

    <xsl:variable name="name" select="//name"/>
    <xsl:variable name="phone" select="//phone"/>
    <xsl:variable name="address" select="//address"/>

      <xsl:for-each select="$name">
        <xsl:if test="(position() mod 4) = 1">
          <xsl:variable name="position" select="position()"/>

          <div class="group">
            <xsl:call-template name="group">
              <xsl:with-param name="name" select="."/>
               <xsl:with-param name="phone" select="."/>
                <xsl:with-param name="address" select="."/>
            </xsl:call-template>

          </div>
        </xsl:if>
      </xsl:for-each>

  </xsl:template>
</xsl:stylesheet>

如果有人可以请更正我的错误吗?非常感谢

2 个答案:

答案 0 :(得分:3)

我根本不会使用for-each。以下样式表以更惯用的方式解决您的问题:

<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <!-- the number of items to include in each group -->
    <xsl:variable name="group" select="3" />
    <xsl:template match="/">
        <xsl:apply-templates select="contact/person[position() mod $group = 1]" />
    </xsl:template>
    <xsl:template match="person">
        <div class="group">
            <xsl:apply-templates
                select=".|following-sibling::person[position() &lt; $group]" 
                  mode="inner" />
        </div>
    </xsl:template>
    <xsl:template match="person" mode="inner">
        <div class="info">
            <xsl:apply-templates />
        </div>
    </xsl:template>
    <xsl:template match="name">
        <h2><xsl:apply-templates /></h2>
    </xsl:template>
    <xsl:template match="phone">
        <h3><xsl:apply-templates /></h3>
    </xsl:template>
    <xsl:template match="address">
        <p><xsl:apply-templates /></p>
    </xsl:template>
</xsl:stylesheet>

我们选择每三分之一person(从第一个开始)并将一个特殊模板(使用模式)应用于该元素及其后两个兄弟姐妹。

答案 1 :(得分:1)

  

如果有人可以请更正我的错误吗?

我不知道我是否可以纠正你的错误,因为我真的不明白你的样式表在哪里。你似乎有正确的想法,这里需要一个处理模板,但之后我就失去了你。

尝试以下方法:

<?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="/">
<root>
    <xsl:call-template name="divide">
        <xsl:with-param name="items" select="contact/person"/>
    </xsl:call-template>
</root>
</xsl:template>

<xsl:template name="divide">
    <xsl:param name="items" />
    <xsl:param name="groupSize" select="3"/>
    <xsl:param name="i" select="1"/>
    <xsl:choose>
        <xsl:when test="$i > count($items)"/>
        <xsl:otherwise>
            <div class="group">
                <xsl:for-each select="$items[$i &lt;= position() and position() &lt; $i+$groupSize]">
                    <div class="info">
                        <h2><xsl:value-of select="name"/></h2>
                        <h3><xsl:value-of select="phone"/></h3>
                        <p><xsl:value-of select="address"/></p>
                    </div>
                </xsl:for-each> 
            </div>
            <xsl:call-template name="divide">
                <xsl:with-param name="items" select="$items"/>
                <xsl:with-param name="i" select="$i+$groupSize"/>
            </xsl:call-template>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>

</xsl:stylesheet>

请注意,我在输出中添加了一个<root>元素,这是您所需输出中缺少的。当我到达时,您的输入也无效:<person>标签未关闭。