tags:

views:

82

answers:

1

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 -->
<xsl:template match="/">

<div class="coGuildName">
 <xsl:element name="img">
  <xsl:attribute name="src">
   <xsl:text>http://champions-online.com&lt;/xsl:text&gt;
   <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.

+3  A: 

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"&gt;

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

    <xsl:variable name="server">
        <xsl:text>http://champions-online.com/super_groups/Phoenix%20Force/xml&lt;/xsl:text&gt;
    </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"&gt;

    <xsl:output method="html"/>

    <xsl:variable name="server">
        <xsl:text>http://champions-online.com/super_groups/Phoenix%20Force/xml&lt;/xsl:text&gt;
    </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}"/&gt;
        </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>
Lachlan Roche
Wow, thanks for this! it is much more simple than what I was piecing together from other examples. I've updated my question on how to integrate your XSL with what I already have done. And as you can see in my code, I was calling the "morepages" template which I have included in my second update. Thanks for the help so far!
fudgey
Thanks again! I had to change the select inside the `<tbody>` to "SuperGroup/members/members_node" to get the correct output, but it is still only showing the first page. The initial page is actually page "1", but I'm not sure if that is the problem.
fudgey
Oops, never mind you were right, it does start with page 0.
fudgey
That apply-templates needs to select "member" as that template does the fetching of the other pages.
Lachlan Roche
Yeah I see that now after I've spent some time trying to understand the code. The problem is with the way it is now, I get this output (http://i40.tinypic.com/11l7rm9.jpg). It's adding the `<member_node>` as if it is HTML.
fudgey
I guess because it was late last night, I copied the code wrong (which produced the output in that image). So, I copied everything from your answer over again and I'm back to the XSL only loading the first page. From messing around with the code, it seems that the line with the `document()` isn't working. Do you have any idea about what the trouble might be? I do greatly appreciate your help thus far.
fudgey
@fudgey Could you ask this last comment as a question. The answer will be more discoverable for others who have the same problem.
Lachlan Roche
@fudgey `document()` not working could be permissions, or proxy server settings for the XSLT processor
Lachlan Roche
Well there is no way for me to confirm that the code is working, but I'm going to go ahead and accept this answer. The guild hosting site added their own script to read the XML feed so this one isn't necessary anymore. Thanks for all your help!
fudgey