sharepointxsltdataviewwebpart

sharepoint data view web part xslt without schema


I'm trying to use a data view web part (via SPD 2007) to consume the results of a SOAP-based web service and render portions of said results using XSL transforms. The problem I'm having is that the designer isn't much help because the schema for the web service doesn't actually include the elements of the results, so there's no way to drag and drop from the data source into the web part, and the manual transforms I've attempted aren't working.

Here is the definition of the web service:

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <GetQuote xmlns="http://www.webserviceX.NET/">
      <symbol>string</symbol>
    </GetQuote>
  </soap:Body>
</soap:Envelope>

And the definition of the response:

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <GetQuoteResponse xmlns="http://www.webserviceX.NET/">
      <GetQuoteResult>string</GetQuoteResult>
    </GetQuoteResponse>
  </soap:Body>
</soap:Envelope>

The query definition is no problem - you just supply a stock ticker symbol as a string. You'll see what I'm talking about in the results, though. It defines the result as just a string.

In SPD2007, the data source pretty much only includes soap:Envelope/soap:Body/GetQuoteResponse/GetQuoteResult, but the actual results contained in the result string look like this:

<StockQuotes>
  <Stock>
    <Symbol>MSFT</Symbol>
    <Last>28.465</Last>
    <Date>3/3/2010</Date>
    <Time>1:24pm</Time>
    <Change>+0.005</Change>
    <Open>28.52</Open>
    <High>28.61</High>
    <Low>28.35</Low>
    <Volume>28380812</Volume>
    <MktCap>249.7B</MktCap>
    <PreviousClose>28.46</PreviousClose>
    <PercentageChange>+0.02%</PercentageChange>
    <AnnRange>14.87 - 31.50</AnnRange>
    <Earns>1.815</Earns>
    <P-E>15.68</P-E>
    <Name>Microsoft Corpora</Name>
  </Stock>
</StockQuotes>

I've tried setting up an XSL stylesheet like this in the data view web part:

<xsl:stylesheet xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
                        xmlns:ddw1="http://www.webserviceX.NET/"
                        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="yes"/>
            <xsl:param name="dvt_apos">'</xsl:param>
            <xsl:template match="/soap:Envelope/soap:Body/ddw1:GetQuoteResponse">
                <xsl:value-of select="*" />             
            </xsl:template>
        </xsl:stylesheet>

This does pretty much what you would expect: it renders the entire result string. However, if I replace

<xsl:template match="/soap:Envelope/soap:Body/ddw1:GetQuoteResponse">
  <xsl:value-of select="*" />               
</xsl:template>

with

<xsl:template match="/soap:Envelope/soap:Body/ddw1:GetQuoteResponse">
  <xsl:value-of select="//Symbol" />                
</xsl:template>

I get nothing. What's going on? how do I use XSL to pick out the XML in the string result without a schema?


Solution

  • In looking at the service you are using it does return the values in a string with < making it look like XML. I can't imagine why they would do this, but you'll need to parse the string as XML in order to process it. There is no native XSLT function to do this, so you'll have to use an extension function. I don't know of one from Microsoft so you'll have to write your own.

    Fortunately there is a good example in this post of this exact question. This person ended up using a custom extension function written in c# to convert the string to XML and then pass it back to the XSLT for regular processing. The custom function they use is:

    <msxml:script language="CSharp" implements-prefix="cd">
    <msxml:using namespace="System.IO" />
    
        public XPathNodeIterator parse(string data) {
            if(data==null || data.Length==0) {
                data="&lt;Empty /&gt;";
            }
            StringReader stringReader = new StringReader(data);
            XPathDocument xPathDocument = new XPathDocument(stringReader);
            XPathNavigator xPathNavigator = xPathDocument.CreateNavigator();
            XPathExpression xPathExpression = xPathNavigator.Compile("/");
            XPathNodeIterator xPathNodeIterator = xPathNavigator.Select(xPathExpression);
            return xPathNodeIterator;
        }
    </msxml:script>
    

    And then you call the function on your string:

    <xsl:variable name="theXML" select="string(/string)" />
    <xsl:variable name="list" select="cd:parse($theXML)" />
    

    I can't guarantee that the custom function will work exactly the way you need it, but it should hopefully get you close.