Displaying Subwebs

Overview
A DataView webpart is a nice component to display SharePoint data. It can connect to various data sources including SharePoint web services which are located under http://[server]/_vti_bin. Here I'd like to show how you can display sub sites on a DataView webpart using SharePoint webs.asmx web service. With this approach, you can easily expose sub sites without any coding.

Configuration


Step1:
Open a SharePoint Designer, open a web site, and double click the page that you'd like to modify.

Step 2:
From the menu bar, click "Insert" -> "SharePoint Controls" -> "Data View."

Step 3:
Click "Connect to a web service..." from the Data Source Library section on the right pane.



Step 4:
Connect to SharePoint Webs.asmx service by typing http://[site url]/_vti_bin/Webs.asmx, click the "Connect" button, and select "GetAllSubWebCollection" operation as shown below:


Step 5:
Provide an appropriate Login information. I chose "Use Windows authentication." Click "OK" to close the Data Source Properties window. FYI, I once had an issue with "Use Single Sign-On authentication" before when I tried to use SSO for a DataView webpart. I wonder if it's a bug in SharePoint or my mistake.


Step 6:
Hover over to the dropdown arrow of the newly created web service connection, and select "Show Data."



Step 7:
Select both Title and Url fields from the Data Source Details pane, and drag-and-drop to the DataView webpart as shown below:

Step 8:

Save the change of the page.

Step 9:

As shown below, the page displays a newly added DataView webpart which shows all sub sites.



Step 10:
Now, let's customize the web part a little bit so that the web part is more useful. Select "Modify Shared Web Part" as shown below:



Step 11:
From the editor web part, click the "XSL Editor..." button.

Step 12:
Select all contents of the XSL Editor, copy and paste the copied contents to a notepad to create a file named "SubWebs.xsl" on your local computer.


Step 13:
Let's modify the XSL code in the SubWebs.xsl using a notepad.

This is the original content:

<xsl:stylesheet xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ddw1="http://schemas.microsoft.com/sharepoint/soap/" version="1.0" exclude-result-prefixes="xsl msxsl ddwrt" xmlns:ddwrt="http://schemas.microsoft.com/WebParts/v2/DataView/runtime" xmlns:asp="http://schemas.microsoft.com/ASPNET/20" xmlns:__designer="http://schemas.microsoft.com/WebParts/v2/DataView/designer" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:SharePoint="Microsoft.SharePoint.WebControls" xmlns:ddwrt2="urn:frontpage:internal">
    <xsl:output method="html" indent="no"/>
    <xsl:decimal-format NaN=""/>
                <xsl:param name="dvt_apos">'</xsl:param>
                <xsl:variable name="dvt_1_automode">0</xsl:variable>
                <xsl:template match="/">
                    <xsl:call-template name="dvt_1"/>
    </xsl:template>
                <xsl:template name="dvt_1">
                    <xsl:variable name="dvt_StyleName">Table</xsl:variable>
                    <xsl:variable name="Rows" select="/soap:Envelope/soap:Body/ddw1:GetAllSubWebCollectionResponse/ddw1:GetAllSubWebCollectionResult/ddw1:Webs/ddw1:Web"/>
        <table border="0" width="100%" cellpadding="2" cellspacing="0">
            <tr valign="top">
                <xsl:if test="$dvt_1_automode = '1'" ddwrt:cf_ignore="1">
                    <th class="ms-vh" width="1%" nowrap="nowrap"></th>
                </xsl:if>
                <th class="ms-vh" nowrap="nowrap">Title</th>
                <th class="ms-vh" nowrap="nowrap">Url</th>
            </tr>
            <xsl:call-template name="dvt_1.body">
                <xsl:with-param name="Rows" select="$Rows"/>
            </xsl:call-template>
        </table>
    </xsl:template>
                <xsl:template name="dvt_1.body">
                    <xsl:param name="Rows"/>
                    <xsl:for-each select="$Rows">
                        <xsl:call-template name="dvt_1.rowview"/>
        </xsl:for-each>
    </xsl:template>
                <xsl:template name="dvt_1.rowview">
        <tr>
            <xsl:if test="position() mod 2 = 1">
                <xsl:attribute name="class">ms-alternating</xsl:attribute>
            </xsl:if>
            <xsl:if test="$dvt_1_automode = '1'" ddwrt:cf_ignore="1">
                <td class="ms-vb" width="1%" nowrap="nowrap">
                    <span ddwrt:amkeyfield="" ddwrt:amkeyvalue="string($XPath)" ddwrt:ammode="view"></span>
                </td>
            </xsl:if>
            <td class="ms-vb">
                <xsl:value-of select="@Title"/>
            </td>
            <td class="ms-vb">
                <xsl:value-of select="@Url"/>
            </td>
        </tr>
    </xsl:template>
</xsl:stylesheet>




This is the modified XSL (I highlighted the modified portion in red color):

<xsl:stylesheet xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ddw1="http://schemas.microsoft.com/sharepoint/soap/" version="1.0" exclude-result-prefixes="xsl msxsl ddwrt" xmlns:ddwrt="http://schemas.microsoft.com/WebParts/v2/DataView/runtime" xmlns:asp="http://schemas.microsoft.com/ASPNET/20" xmlns:__designer="http://schemas.microsoft.com/WebParts/v2/DataView/designer" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:SharePoint="Microsoft.SharePoint.WebControls" xmlns:ddwrt2="urn:frontpage:internal">
    <xsl:output method="html" indent="no"/>
    <xsl:decimal-format NaN=""/>
                <xsl:param name="dvt_apos">'</xsl:param>
                <xsl:variable name="dvt_1_automode">0</xsl:variable>
                <xsl:template match="/">
                    <xsl:call-template name="dvt_1"/>
    </xsl:template>
                <xsl:template name="dvt_1">
                    <xsl:variable name="dvt_StyleName">Table</xsl:variable>
                    <xsl:variable name="Rows" select="/soap:Envelope/soap:Body/ddw1:GetAllSubWebCollectionResponse/ddw1:GetAllSubWebCollectionResult/ddw1:Webs/ddw1:Web"/>
        <table border="0" width="100%" cellpadding="2" cellspacing="0">
            <tr valign="top">
                <xsl:if test="$dvt_1_automode = '1'" ddwrt:cf_ignore="1">
                    <th class="ms-vh" width="1%" nowrap="nowrap"></th>
                </xsl:if>
                <th class="ms-vh" nowrap="nowrap">Subsites</th>
            </tr>
            <xsl:call-template name="dvt_1.body">
                <xsl:with-param name="Rows" select="$Rows"/>
            </xsl:call-template>
        </table>
    </xsl:template>
                <xsl:template name="dvt_1.body">
                    <xsl:param name="Rows"/>
                    <xsl:for-each select="$Rows">
                        <xsl:call-template name="dvt_1.rowview"/>
        </xsl:for-each>
    </xsl:template>
                <xsl:template name="dvt_1.rowview">
        <tr>
            <xsl:if test="position() mod 2 = 1">
                <xsl:attribute name="class">ms-alternating</xsl:attribute>
            </xsl:if>
            <xsl:if test="$dvt_1_automode = '1'" ddwrt:cf_ignore="1">
                <td class="ms-vb" width="1%" nowrap="nowrap">
                    <span ddwrt:amkeyfield="" ddwrt:amkeyvalue="string($XPath)" ddwrt:ammode="view"></span>
                </td>
            </xsl:if>
            <td class="ms-vb">
                <a>
                    <xsl:attribute name="href">
                        <xsl:value-of select="@Url"/>
                    </xsl:attribute>
                    <xsl:value-of select="@Title"/>
                </a>

            </td>
        </tr>
    </xsl:template>
</xsl:stylesheet>




Step 13:
Upload the saved XSL file to a SharePoint document library. The ideal place would be "Style Library," but it's up to you where to upload a file. Please make sure that everybody will have a read access to this file. Copy the URL of the XSL file, i.e. "/Style Library/SubWebs.xsl."
Step 14:

Go back to the DataView web part, edit the web part as explained in Step 10. Under the Miscellaneous section of the editor webpart, you will see XSL Link textbox. Fill in the XSL Link textbox with the copied URL from Step 13, i.e. "/Style Library/SubWebs.xsl." Click "OK" to save the change.

Step 15:
Now we're done. The DataView web part is using a modified XSL file to display sub sites in hyperlinks.






Summary & After-thought
As shown, you can configure a DataView webpart to display sub sites pretty quickly without any coding by consuming SharePoint web services. I would use this approach for a relatively small intranet with small to medium web traffic. For heavy traffic intranet with tons of sub sites, I'd recommend a more robust approach which would require custom coding.