开发者

Making an XSL stylesheet work with paged XML

First off, here is the situation. I'm using a guild hosting site that allows you to input the URL to an XSL file and another input for the XML. All well and good when all of the XML you want is contained in one file.

My problem is this Game Roster XML which is paginated... look near the bottom of the file and you will find a <page_links> section that contains a pager written in HTML with links to /xml?page=2 etc. Since the guild hosting site is set up to only process one XML page I can't get to the other XML pages.

So, I can only think of two solutions, but I have no idea how to get started

  1. Set up a php page that combines all XML pages into one, then output that file. I can then use this URL in the guild hosting site XSL processor.
  2. Somehow combine all the XML files within the XSL stylesheet. I found this question on SO (I don't really understand it, because I don't know what the document($pXml1) is doing), but I don't think it will work since the number of pages will be variable. I think this might be possible by loading the next page until the <members_to> value equals the <members_total>.

Any other ideas? I don't know XSL or php that well so any help with code examples would be greatly appreciated.


Update: I'm trying method 2 above and here is a snippet of XSLT with which I am having trouble. The first page of the code displays without problems, but the I am having trouble with this xsl:if, or maybe it's the document() statement.

Update #2: changed the document to use the string & concat functions, but it's still not working.

<xsl:template name="morepages">

 <xsl:param name="page">1</xsl:param>
 <xsl:param name="url">
  <xsl:value-of select="concat(SuperGroup/profule_url,'/xml?page=')"/>
 </xsl:param> 

 <xsl:if test="document(string(concat($url,$page)))/SuperGroup/members_to &lt; document(string(concat($url,$page)))/SuperGroup/members_total">
   <xsl:for-each select="document(string(concat($url,$page + 1)))/SuperGroup/members/members_node">
   <xsl:call-template name="addrow" />
  </xsl:for-each>
  <!-- Increment page index-->
  <xsl:call-template name="morepages">
   <xsl:with-param name="page" select="$page + 1"/>
  </xsl:call-template>
 </xsl:if>
</xsl:template>

Update #3: Thanks for that great start Lachlan! But I'm trying to output this in HTML. I have an "addrow" template and a main template which I'm not sure how to integrate together with the XSL you provided. Here is what I have:

 <!-- add a member row -->
 <xsl:template name="addrow">
  <tr>
   <td class="coName">
    <xsl:element name="a">
     <xsl:attribute name="target">
      <xsl:text>_blank</xsl:text>
     </xsl:attribute>
     <xsl:attribute name="href">
      <xsl:value-of select="profile_url"/>
     </xsl:attribute>
    <xsl:value-of select="pcname"/>
    </xsl:element>
   </td>
   <xsl:element name="td">
    <xsl:attribute name="class">
     <xsl:text>coAccount</xsl:text>
    </xsl:attribute>
    <xsl:value-of select="pcaccount"/>
   </xsl:element>
   <td class="coLevel"><xsl:value-of select="ilevel"/></td>
   <xsl:if test="irank!=''">
    <td class="coRank">
     <xsl:value-of select="irank"/>
    </td>
   </xsl:if>
   <td class="coStatus"><xsl:value-of select="pcmapname"/></td>
  </tr>
 </xsl:template>


<!-- main template --&开发者_如何学JAVAgt;
<xsl:template match="/">

<div class="coGuildName">
 <xsl:element name="img">
  <xsl:attribute name="src">
   <xsl:text>http://champions-online.com</xsl:text>
   <xsl:value-of select="SuperGroup/guild_name_img"/>
  </xsl:attribute>
 </xsl:element>
</div>

<table width="100%" cellspacing="0" cellpadding="0" id="coRoster" align="center">
 <thead>
  <tr class="ForumCategoryHeader">
   <th class="coName">Name</th>
   <th class="coAccount">Account</th>
   <th class="coLevel">Level</th>

   <xsl:if test="SuperGroup/ranks!=''">
    <th class="coRank">Rank</th>
   </xsl:if>

   <th class="coStatus">Status</th>
  </tr>
 </thead>
 <tbody>

 <xsl:for-each select="SuperGroup/members/members_node">
  <xsl:call-template name="addrow" />
 </xsl:for-each>

 <!-- if less then total members shown, load next XML page -->
 <xsl:if test="SuperGroup/members_to &lt; SuperGroup/members_total">
  <xsl:call-template name="morepages"/>
 </xsl:if>

 </tbody>
</table>
</xsl:template>

Update #4: I'm still stuck. This XSL won't load any additional XML pages. I have tried adding SuperGroup[position()] to the SuperGroup and members template without success. I have also tried reformatting the code to something similar to this post and still no luck. I would appreciate any other ideas.


This stylesheet takes page "0" as the input document. In the members template we check for more pages and apply the "next-page" SuperGroup template if needed. This last template computes the page number and fetches the members element from the next document.

<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:output method="xml" indent="yes"/>

    <xsl:variable name="server">
        <xsl:text>http://champions-online.com/super_groups/Phoenix%20Force/xml</xsl:text>
    </xsl:variable>

    <xsl:template match="SuperGroup">
        <members>
            <xsl:apply-templates select="members"/>
        </members>
    </xsl:template>

    <xsl:template match="members">
        <xsl:copy-of select="members_node" />
        <xsl:if test="/SuperGroup/members_total != /SuperGroup/members_to">
            <xsl:apply-templates select="/SuperGroup" mode="next-page" />
        </xsl:if>
    </xsl:template>

    <xsl:template match="SuperGroup" mode="next-page">
        <xsl:variable name="this" select="(members_from - 1) div 20" />
        <xsl:variable name="page" select="1 + $this" />
        <xsl:variable name="url" select="concat($server,'?page=',$page)" />

        <xsl:apply-templates select="document($url)/SuperGroup/members" />
    </xsl:template>

</xsl:stylesheet>

Merging that with your main stylesheet from example 3 we get the following.

I have made some general improvements: use literal result elements instead of xsl:element as the names are not dynamic; use attribute value templates instead of xsl:attribute.

<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:output method="html"/>

    <xsl:variable name="server">
        <xsl:text>http://champions-online.com/super_groups/Phoenix%20Force/xml</xsl:text>
    </xsl:variable>

    <xsl:template match="members_node">
        <tr>
            <td class="coName">
                <a target="_blank" href="{profile_url}">
                    <xsl:value-of select="pcname"/>
                </a>
            </td>
            <td class="coAccount">
                <xsl:value-of select="pcaccount"/>
            </td>
            <td class="coLevel">
                <xsl:value-of select="ilevel"/>
            </td>
            <xsl:if test="irank!=''">
                <td class="coRank">
                    <xsl:value-of select="irank"/>
                </td>
            </xsl:if>
            <td class="coStatus">
                <xsl:value-of select="pcmapname"/>
            </td>
        </tr>
    </xsl:template>

    <xsl:template match="/">
        <div class="coGuildName">
            <img src="http://champions-online.com{SuperGroup/guild_name_img}"/>
        </div>
        <table width="100%" cellspacing="0" cellpadding="0" id="coRoster" align="center">
            <thead>
                <tr class="ForumCategoryHeader">
                    <th class="coName">Name</th>
                    <th class="coAccount">Account</th>
                    <th class="coLevel">Level</th>
                    <xsl:if test="SuperGroup/ranks!=''">
                        <th class="coRank">Rank</th>
                    </xsl:if>
                    <th class="coStatus">Status</th>
                </tr>
            </thead>
            <tbody>
                <xsl:apply-templates select="SuperGroup/members" />
            </tbody>
        </table>
    </xsl:template>

    <xsl:template match="members">
        <xsl:apply-templates select="members_node" />
        <xsl:if test="/SuperGroup/members_total != /SuperGroup/members_to">
            <xsl:apply-templates select="/SuperGroup" mode="next-page" />
        </xsl:if>
    </xsl:template>

    <xsl:template match="SuperGroup" mode="next-page">
        <xsl:variable name="this" select="(members_from - 1) div 20" />
        <xsl:variable name="page" select="1 + $this" />
        <xsl:variable name="url" select="concat($server,'?page=',$page)" />
        <xsl:apply-templates select="document($url)/SuperGroup/members" />
    </xsl:template>

</xsl:stylesheet>
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜