A few samples of the power of X# and XML-oriented programming.
Relational Databases
Retrieve all RSS Feeds from NY Times and save those entries containing the word oil in a MySQL database titled oil_news:
<xsp:append-child target="document('xdbc:mysql://192.168.1.27:3306/maindb')/oil_news">
<xsp:for-each
select="(document('http://www.nytimes.com/services/xml/rss/nyt/HomePage.xml')/text() >> /library/xml/pi('import'))/channel/item[contains(title,'oil')]">
<row>
<title><xsp:text value="{title}"/></title>
<description><xsp:text value="{description}"/></description>
<link><xsp:text value="{link}"/></link>
</row>
</xsp:for-each>
</xsp:append-child>
Update an Oracle table containing customers with a map image obtained from Yahoo Maps:
<xsp:for-each select="document('xdbc:oracle:thin:scott@tiger//myhost:1521/orcl')/customers/*]">
<!-- Update 'image_blob' column of each record with a map image -->
<xsp:append-child target=".">
<image_blob>
<xsp:with>
<xsp:context>
<appid>myapp</appid>
<street><xsp:text value="{STREET}"/></street>
<city><xsp:text value="{CITY}"/></city>
<state><xsp:text value="{STATE}"/></state>
<zip><xsp:text value="{ZIP}"/></zip>
</xsp:context>
<xsp:do>
<!-- Contact Yahoo Maps Web Service and obtain map URL-->
<xsp:variable name="map-url" type="string"
select="* >> document('rest:[http://local.yahooapis.com/MapsService/V1/mapImage?messagetype=x-www-form&httpmethod=get')/text()"/>]
<!-- Download image and return a binary text node -->
<?xpath document($map-url)/text() ?>
</xsp:do>
</xsp:with>
</image_blob>
</xsp:append-child>
<!-- Update database -->
<xsp:update-node select="."/>
</xsp:for-each>
E-mail
A fully working e-mail auto-responder using only two statements. Automatically sends a message to the senders of all unseen messages in your Inbox.
<xsp:for-each select="document('imaps://imap.gmail.com?user=jkirk@gmail.com&pass=secret')/folder[@name='INBOX']/mail[@seen = 'false']">
<xsp:append-child target="document('smtp://smtp.gmail.com')">
<mail subject="{concat('RE: ', @subject)}" from="jkirk@gmail.com" to="{addresses/from/@address}">
Hi <xsp:text value="{addresses/from/@name}"/>,
I've received your message titled '<xsp:text value="{@subject}"/>' and
I will reply to it shortly.
--James
</mail>
</xsp:append-child>
</xsp:for-each>
Send an e-mail including an Excel attachment using also two statements:
<xsp:append-child target="document('smtp://smtp.gmail.com')">
<mail subject="Report" from="jdoe@gmail.com" to="recipient@xsharp.org">
<contents>
<body>Contents go here</body>
<file name="report.xls">
<xsp:with>
<xsp:context>
<workbook>
<sheet name="My Report">
<row>
<cell>Name</cell>
<cell>Earnings</cell>
<cell>Quarter</cell>
</row>
<row>
<cell>John Doe</cell>
<cell>900873.44</cell>
<cell>Q1</cell>
</row>
</sheet>
</workbook>
</xsp:context>
<xsp:execute select="/library/excel/pi('export')"/>
</xsp:with>
</file>
</contents>
</mail>
</xsp:append-child>
Migrate your Microsoft Exchange folders and messages to Gmail using one statement:
<xsp:append-child target="document('imaps://imap.gmail.com?user=jkirk@gmail.com&pass=secret')"
select="document('imap://exchange.microsoft.com?user=jkirk&pass=secret')/*"/>
Files
Create a ZIP file containing all documents under the public Windows shared folder.
<xsp:append-child target="document('file:///home/jkirk')">
<file name="documents.zip">
<?xpath document('document('smb://administrator:foobar@192.168.1.77/public')')//file[ends-with(@name,'.doc')] >> /library/compress/pi('zip') ?>
</file>
</xsp:append-child>
Upload all files under /home/jkirk/documents to an FTP server using a separate thread per file:
<xsp:append-child target="/threads">
<xsp:for-each select="document('file:///home/jkirk/documents')//file">
<xsp:variable name="file" type="node" select="."/>
<xsp:pi>
<xsp:append-child target="document('ftp://ftp.domain.com?user=jj&pass=12345')/directory[@name='upload']" select="$file"/>
</xsp:pi>
</xsp:for-each>
</xsp:append-child>
Consuming Web Services
The following Web application expects the query parameter and performs a search using the Yahoo search Web service, results are returned in an Excel file:
<xsp:pi xmlns:xsp="[http://www.xsharp.org/2008/xxml">]
<xsp:set-attribute target="http-response" name="content-type">application/vnd.ms-excel</xsp:set-attribute>
<xsp:set-attribute target="http-response/headers" name="Content-Disposition" select="'attachment; filename=yahoo_search.xls'"/>
<xsp:with>
<xsp:context>
<xsp:with>
<xsp:context>
<appid>xsharp</appid>
<query><xsp:value-of select="http-request/parameters/query"/></query>
</xsp:context>
<xsp:execute select="document('rest:[http://search.yahooapis.com/WebSearchService/V1/webSearch?messagetype=x-www-form&httpmethod=get')"/>]
</xsp:with>
</xsp:context>
<xsp:do>
<xsp:with>
<xsp:context>
<workbook>
<sheet name="Search Results">
<row><cell>URL</cell><cell>Title</cell><cell>Summary</cell></row>
<xsp:for-each select="ResultSet/Result">
<row><cell><?xpath Url/text()?></cell>
<cell><?xpath Title/text()?></cell>
<cell><?xpath Summary/text()?></cell></row>
</xsp:for-each>
</sheet>
</workbook>
</xsp:context>
<xsp:execute select="/library/excel/pi('export')"/>
</xsp:with>
</xsp:do>
</xsp:with>
</xsp:pi>
The following Web application expects the zip parameter and returns the weather and city name using a SOAP Web service:
<xsp:pi xmlns:xsp="[http://www.xsharp.org/2008/xxml">]
<html>
<xsp:with>
<xsp:context>
<xsp:with>
<xsp:context>
<ZIP><xsp:text value="{http-request/parameters/zip}"/></ZIP>
</xsp:context>
<xsp:execute select="document('soap:[http://ws.cdyne.com/WeatherWS/Weather.asmx?operation=GetCityWeatherByZIP&action=http://ws.cdyne.com/WeatherWS/GetCityWeatherByZIP&namespace=http://ws.cdyne.com/WeatherWS/')"/>]
</xsp:with>
</xsp:context>
<xsp:do>
<h1>Temparature in <xsp:text value="{*/*/City}"/> is <xsp:text value="{*/*/Temperature}"/>F.</h1>
</xsp:do>
</xsp:with>
</html>
</xsp:pi>
Creating Web Services
Web services are created using the xws file extension. The following example demonstrates a "Hello World" Web service in one line:
<xsp:processing-instruction name="helloWorld">Hello World, <xsp:text value="{*/name}"/>!</xsp:processing-instruction>
A Calculator Web service that executes the requested operation from a function library:
<!-- Define 'calculatorService' operation -->
<xsp:processing-instruction name="calculatorService">
<!-- Obtain web service parameters -->
<xsp:variable name="request" type="node" select="*"/>
<xsp:with>
<xsp:context>
<!-- Registered operations -->
<xsp:processing-instruction name="+">
<xsp:text value="{node()[1] + node()[2]}"/>
</xsp:processing-instruction>
<xsp:processing-instruction name="-">
<xsp:text value="{node()[1] - node()[2]}"/>
</xsp:processing-instruction>
<xsp:processing-instruction name="/">
<xsp:text value="{node()[1] div node()[2]}"/>
</xsp:processing-instruction>
<xsp:processing-instruction name="*">
<xsp:text value="{node()[1] * node()[2]}"/>
</xsp:processing-instruction>
</xsp:context>
<xsp:execute select="$request/left | $request/right >> processing-instruction()[name() = $request/operation]"/>
</xsp:with>
</xsp:processing-instruction>
Functional Programming with X#
For those who love functional programming, here we demonstrate how to create a map function:
<!-- MAP function -->
<xsp:variable name="map" type="node">
<xsp:processing-instruction name="map">
<xsp:variable name="function" type="node" select="processing-instruction()"/>
<xsp:processing-instruction name="result">
<xsp:for-each select="node()">
<?xpath . >> $function ?>
</xsp:for-each>
</xsp:processing-instruction>
</xsp:processing-instruction>
</xsp:variable>
<!-- SQUARE function -->
<xsp:variable name="square" type="node">
<xsp:processing-instruction>
<xsp:text value="{node() * node()}"/>
</xsp:processing-instruction>
</xsp:variable>
<!-- Returns '1', '4', '9', '16', '25' -->
<?xpath 1 .. 5 >> ($square >> $map) ?>
Or, we could compose functions as follows:
<!-- COMPOSE function -->
<xsp:variable name="compose" type="node">
<xsp:processing-instruction name="compose">
<xsp:variable name="functions" type="nodelist" select="processing-instruction()"/>
<xsp:processing-instruction name="result">
<xsp:variable name="result" type="nodelist" select="node()"/>
<xsp:for-each select="$functions">
<xsp:set-variable name="result" select="$result >> ."/>
</xsp:for-each>
<?xpath $result ?>
</xsp:processing-instruction>
</xsp:processing-instruction>
</xsp:variable>
<!-- Create a function to Tokenize a string by commas -->
<xsp:variable name="tokenizer" type="node">
<xsp:processing-instruction name="tokenizer">
<?xpath tokenize(node(),',') ?>
</xsp:processing-instruction>
</xsp:variable>
<!-- Use compose to create a new function that
tokenizes by commas and calculates squares -->
<xsp:variable name="token-sqr" type="node" select="$tokenizer | ($square >> $map) >> $compose"/>
<!-- Returns '1', '9', '25', '49' -->
<?xpath new-text('1,3,5,7') >> $token-sqr ?>