排序 xslt 模板样式问题

发布于 2024-10-26 02:35:10 字数 3524 浏览 1 评论 0原文

我正在尝试设置一些 xml 的样式:

<campers>
  <camper>
    <firstname>James</firstname>
    <lastname>West</lastname>
    <gender>Boy</gender>
  </camper>
  <camper>
    <firstname>Adam</firstname>
    <lastname>West</lastname>
    <gender>Boy</gender>
  </camper>
  <camper>
    <firstname>Ann</firstname>
    <lastname>Landers</lastname>
    <gender>Girl</gender>
  </camper>
  <camper>
    <firstname>Billy</firstname>
    <lastname>Batson</lastname>
    <gender>Boy</gender>
  </camper>
  <camper>
    <firstname>Diana</firstname>
    <lastname>Prince</lastname>
    <gender>Girl</gender>
  </camper>
</campers>

我想让它们按性别然后按名称排序,但我也想按性别设置标题。我似乎无法让它发挥作用。我的输出应如下所示:

Campers

Boys

Batson, Billy
韦斯特,亚当
詹姆斯·韦斯特

安·女孩

·兰德斯
Prince, Diana

使用以下 xsl:

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

  <xsl:output method="html" indent="yes" version="1.0"/>

<xsl:template match="/">
    <html>
    <head><title>Camper list</title></head>
    <body style="font-family:Arial,Helvetica,sans-serif;font-size:8pt;">
    <h2>Campers</h2>
    <xsl:apply-templates select="//camper">
      <xsl:sort select="gender" />
      <xsl:sort select="lastname" />
      <xsl:sort select="firstname" />
    </xsl:apply-templates>
    </body>
    </html>
</xsl:template>

<xsl:template match="camper">
  <xsl:if test="not(gender = preceding::gender)">
    <h3><xsl:value-of select="gender"/>s</h3>
  </xsl:if>
  <xsl:value-of select="lastname"/><xsl:text>, </xsl:text><xsl:value-of select="firstname"/><br />
</xsl:template>

</xsl:stylesheet>

不幸的是,我的输出如下所示:

Campers

Batson, Billy
亚当·韦斯特

男孩

詹姆斯·韦斯特

女孩

安·兰德斯
王子,戴安娜

我确信我在排序上做错了什么,或者排序没有按照我的预期使用。任何建议都会有所帮助。

谢谢,

大卫

附录:基于 lwburk 的解决方案,这就是我想到的:

<xsl:key name="campers-by-gender" match="camper" use="gender" />
<xsl:template match="/">
    <html>
        <head><title>Camper xsl test</title></head>
        <body style="font-family:Arial,Helvetica,sans-serif;font-size:8pt;">
            <h2>Campers</h2>
            <xsl:apply-templates />
        </body>
    </html>
</xsl:template>
<xsl:template match="campers">
    <xsl:for-each select="camper[count(. | key('campers-by-gender', gender)[1]) = 1]">
        <h3><xsl:value-of select="key('campers-by-gender', gender)/gender"/>s</h3>
        <xsl:for-each select="key('campers-by-gender', gender)">
            <xsl:sort select="lastname" />
            <xsl:sort select="firstname" />
            <xsl:value-of select="lastname"/><xsl:text>, </xsl:text><xsl:value-of select="firstname"/><br />
        </xsl:for-each>
    </xsl:for-each>
</xsl:template>

感谢所有的帮助和好主意! D .

I am trying to style some xml:

<campers>
  <camper>
    <firstname>James</firstname>
    <lastname>West</lastname>
    <gender>Boy</gender>
  </camper>
  <camper>
    <firstname>Adam</firstname>
    <lastname>West</lastname>
    <gender>Boy</gender>
  </camper>
  <camper>
    <firstname>Ann</firstname>
    <lastname>Landers</lastname>
    <gender>Girl</gender>
  </camper>
  <camper>
    <firstname>Billy</firstname>
    <lastname>Batson</lastname>
    <gender>Boy</gender>
  </camper>
  <camper>
    <firstname>Diana</firstname>
    <lastname>Prince</lastname>
    <gender>Girl</gender>
  </camper>
</campers>

I want to have them sorted by gender then name, but I also want to have a header by gender. I cannot seem to get this to work. My output should look like this:

Campers

Boys

Batson, Billy
West, Adam
West, James

Girls

Landers, Ann
Prince, Diana

Using the following xsl:

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

  <xsl:output method="html" indent="yes" version="1.0"/>

<xsl:template match="/">
    <html>
    <head><title>Camper list</title></head>
    <body style="font-family:Arial,Helvetica,sans-serif;font-size:8pt;">
    <h2>Campers</h2>
    <xsl:apply-templates select="//camper">
      <xsl:sort select="gender" />
      <xsl:sort select="lastname" />
      <xsl:sort select="firstname" />
    </xsl:apply-templates>
    </body>
    </html>
</xsl:template>

<xsl:template match="camper">
  <xsl:if test="not(gender = preceding::gender)">
    <h3><xsl:value-of select="gender"/>s</h3>
  </xsl:if>
  <xsl:value-of select="lastname"/><xsl:text>, </xsl:text><xsl:value-of select="firstname"/><br />
</xsl:template>

</xsl:stylesheet>

Unfortunately, my output looks like this:

Campers

Batson, Billy
West, Adam

Boys

West, James

Girls

Landers, Ann
Prince, Diana

I am sure I am doing something wrong with the sort, or the sort is not being used as I expect it to be. Any suggestions would help.

Thanks,

David

Addendum: Based on lwburk's solution, here is what I came up with:

<xsl:key name="campers-by-gender" match="camper" use="gender" />
<xsl:template match="/">
    <html>
        <head><title>Camper xsl test</title></head>
        <body style="font-family:Arial,Helvetica,sans-serif;font-size:8pt;">
            <h2>Campers</h2>
            <xsl:apply-templates />
        </body>
    </html>
</xsl:template>
<xsl:template match="campers">
    <xsl:for-each select="camper[count(. | key('campers-by-gender', gender)[1]) = 1]">
        <h3><xsl:value-of select="key('campers-by-gender', gender)/gender"/>s</h3>
        <xsl:for-each select="key('campers-by-gender', gender)">
            <xsl:sort select="lastname" />
            <xsl:sort select="firstname" />
            <xsl:value-of select="lastname"/><xsl:text>, </xsl:text><xsl:value-of select="firstname"/><br />
        </xsl:for-each>
    </xsl:for-each>
</xsl:template>

Thanks for all the help and good ideas!
D.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

风流物 2024-11-02 02:35:10

您需要先分组然后排序:

<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="html" indent="yes" version="1.0"/>
    <xsl:key name="gender" match="camper" use="gender" />
    <xsl:template match="/">
        <html>
        <head><title>Camper list</title></head>
        <body style="font-family:Arial,Helvetica,sans-serif;font-size:8pt;">
        <h2>Campers</h2>
        <xsl:apply-templates />
        </body>
        </html>
    </xsl:template>
    <xsl:template
        match="camper[generate-id()=generate-id(key('gender', gender)[1])]">
        <h3><xsl:value-of select="gender" />s</h3>
        <xsl:apply-templates select="key('gender', gender)" mode="out">
            <xsl:sort select="lastname" />
            <xsl:sort select="firstname" />
        </xsl:apply-templates>
    </xsl:template>
    <xsl:template match="camper" mode="out">
        <xsl:value-of select="lastname" />
        <xsl:text>, </xsl:text>
        <xsl:value-of select="firstname" />
        <br />
    </xsl:template>
    <xsl:template match="camper" />
</xsl:stylesheet>

这会在源文档上产生以下输出:

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Camper list</title>
</head>
<body style="font-family: Arial,Helvetica,sans-serif; font-size: 8pt;">
<h2>Campers</h2>
<h3>Boys</h3>
Batson, Billy<br />
West, Adam<br />
West, James<br />

<h3>Girls</h3>
Landers, Ann<br />
Prince, Diana<br />

You need to group first and then sort:

<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="html" indent="yes" version="1.0"/>
    <xsl:key name="gender" match="camper" use="gender" />
    <xsl:template match="/">
        <html>
        <head><title>Camper list</title></head>
        <body style="font-family:Arial,Helvetica,sans-serif;font-size:8pt;">
        <h2>Campers</h2>
        <xsl:apply-templates />
        </body>
        </html>
    </xsl:template>
    <xsl:template
        match="camper[generate-id()=generate-id(key('gender', gender)[1])]">
        <h3><xsl:value-of select="gender" />s</h3>
        <xsl:apply-templates select="key('gender', gender)" mode="out">
            <xsl:sort select="lastname" />
            <xsl:sort select="firstname" />
        </xsl:apply-templates>
    </xsl:template>
    <xsl:template match="camper" mode="out">
        <xsl:value-of select="lastname" />
        <xsl:text>, </xsl:text>
        <xsl:value-of select="firstname" />
        <br />
    </xsl:template>
    <xsl:template match="camper" />
</xsl:stylesheet>

Which produces the following output on your source document:

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Camper list</title>
</head>
<body style="font-family: Arial,Helvetica,sans-serif; font-size: 8pt;">
<h2>Campers</h2>
<h3>Boys</h3>
Batson, Billy<br />
West, Adam<br />
West, James<br />

<h3>Girls</h3>
Landers, Ann<br />
Prince, Diana<br />

漫雪独思 2024-11-02 02:35:10

我确信还有几种更简单的方法可以做到这一点!

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

        <xsl:output method="html" indent="yes" version="1.0"/>

        <xsl:template match="/">
                <html>
                        <head>
                                <title>Camper list</title>
                        </head>
                        <body style="font-family:Arial,Helvetica,sans-serif;font-size:8pt;">
                                <h2>Campers</h2>
                                <xsl:apply-templates select="//camper[gender='Boy']">  
                                        <xsl:sort select="lastname" />
                                        <xsl:sort select="firstname" />
                                </xsl:apply-templates>
                                <xsl:apply-templates select="//camper[gender='Girl']">
                                        <xsl:sort select="lastname" />
                                        <xsl:sort select="firstname" />
                                </xsl:apply-templates>
                        </body>
                </html>
        </xsl:template>

        <xsl:template match="camper">
                <xsl:if test="position() < 2">
                        <h3>
                                <xsl:value-of select="gender"/>s
                        </h3>
                </xsl:if>
                <xsl:value-of select="lastname"/>
                <xsl:text>, </xsl:text>
                <xsl:value-of select="firstname"/>
                <br />
        </xsl:template>

</xsl:stylesheet>

im sure there are several more simple ways to do this!

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

        <xsl:output method="html" indent="yes" version="1.0"/>

        <xsl:template match="/">
                <html>
                        <head>
                                <title>Camper list</title>
                        </head>
                        <body style="font-family:Arial,Helvetica,sans-serif;font-size:8pt;">
                                <h2>Campers</h2>
                                <xsl:apply-templates select="//camper[gender='Boy']">  
                                        <xsl:sort select="lastname" />
                                        <xsl:sort select="firstname" />
                                </xsl:apply-templates>
                                <xsl:apply-templates select="//camper[gender='Girl']">
                                        <xsl:sort select="lastname" />
                                        <xsl:sort select="firstname" />
                                </xsl:apply-templates>
                        </body>
                </html>
        </xsl:template>

        <xsl:template match="camper">
                <xsl:if test="position() < 2">
                        <h3>
                                <xsl:value-of select="gender"/>s
                        </h3>
                </xsl:if>
                <xsl:value-of select="lastname"/>
                <xsl:text>, </xsl:text>
                <xsl:value-of select="firstname"/>
                <br />
        </xsl:template>

</xsl:stylesheet>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文