如何将每个第三个元素封装到一个div中,每个元素都是xslt

时间:2021-02-18 18:48:33

I am quite newbie on XSLT. here is my XML

我对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>

The OUTPUT I am trying to have

我想要的输出

<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>

Here is what I did, but there are many errors. how to select more 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>

If someone could please correct my errors please? Many thanks

如果有人能帮我改正错误,好吗?非常感谢

2 个解决方案

#1


1  

If someone could please correct my errors please?

如果有人能帮我改正错误,好吗?

I don't know if I can correct your errors, because I don't really understand where you're going with your stylesheet. You seem to have the right idea that a processing template is required here, but I lost you after that.

我不知道我是否能纠正您的错误,因为我真的不理解您的样式表要做什么。您似乎有正确的想法,在这里需要一个处理模板,但是在那之后我就失去了您。

Try the following approach:

试试下面的方法:

<?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>

Note that I have added a <root> element to the output which is missing from your required output. While I am at it, your input is also invalid: the <person> tags are not closed.

注意,我已经在输出中添加了一个 元素,这是您所需要的输出所缺少的。当我在这里时,您的输入也是无效的: 标记没有关闭。

#2


3  

I wouldn't use for-each at all. The following stylesheet solves your problem in a more idiomatic way:

我不会用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>

We select every third person (starting with the first one) and apply a special template (using modes) to that element and its next two siblings.

我们选择每个第三人(从第一个开始),并将一个特殊的模板(使用模式)应用到该元素及其下两个兄弟姐妹。

#1


1  

If someone could please correct my errors please?

如果有人能帮我改正错误,好吗?

I don't know if I can correct your errors, because I don't really understand where you're going with your stylesheet. You seem to have the right idea that a processing template is required here, but I lost you after that.

我不知道我是否能纠正您的错误,因为我真的不理解您的样式表要做什么。您似乎有正确的想法,在这里需要一个处理模板,但是在那之后我就失去了您。

Try the following approach:

试试下面的方法:

<?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>

Note that I have added a <root> element to the output which is missing from your required output. While I am at it, your input is also invalid: the <person> tags are not closed.

注意,我已经在输出中添加了一个 元素,这是您所需要的输出所缺少的。当我在这里时,您的输入也是无效的: 标记没有关闭。

#2


3  

I wouldn't use for-each at all. The following stylesheet solves your problem in a more idiomatic way:

我不会用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>

We select every third person (starting with the first one) and apply a special template (using modes) to that element and its next two siblings.

我们选择每个第三人(从第一个开始),并将一个特殊的模板(使用模式)应用到该元素及其下两个兄弟姐妹。