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 <= position() and position() < $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() < $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 <= position() and position() < $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() < $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.
我们选择每个第三人(从第一个开始),并将一个特殊的模板(使用模式)应用到该元素及其下两个兄弟姐妹。