Eric
Eric

Reputation: 2884

XSLT - transform XML in REST response result

I am currently trying to use XSLT to convert some XML pseudo-code to a rest response result

For example, with the following xml:

<?xml version="1.0" encoding="UTF-8"?>
<root xmlns:functions="http://foo.com/api/rest">
  <item bar="foo">some item</item>
  <functions:fetch a="3" b="foo" />
</root>

And if the result of http://foo.com/services/rest/fetch/a/3/b/foo is:

<?xml version="1.0" encoding="UTF-8"?>
<rsp stat="ok">
  <book>
    <title>Ethics</title>
  </book>
  <book>
    <title>Beyond Good and Evil</title>
  </book>
</rsp>

The result of the XSLT parsing I am trying to obtain is:

<?xml version="1.0" encoding="UTF-8"?>
<root xmlns:functions="http://foo.com/api/rest">
  <item bar="foo">some item</item>
  <book>
    <title>Ethics</title>
  </book>
  <book>
    <title>Beyond Good and Evil</title>
  </book>
</root>

I know I can use <xsl:value-of select="document('http://foo.com/services/rest/fetch/a/3/b/foo')"/> to make the request, but I am stuck on how to generate and process it in the same XSLT.

Any help will be greatly appreciated, Thanks in advance!

Upvotes: 1

Views: 3516

Answers (2)

Eric
Eric

Reputation: 2884

Thanks to the answer from Dimitre, I found a solution!

(I make a new reply as I tuned Dimitre solution a little to work with any function name and multiple functions in the same XML)

Here the xslt:

<xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:functions="http://foo.com/api/rest"
  exclude-result-prefixes="functions">
  <xsl:output omit-xml-declaration="yes" indent="yes"/>
  <xsl:strip-space elements="*"/>

  <xsl:template match="node()|@*">
    <xsl:copy>
      <xsl:apply-templates select="node()|@*"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="/">
    <xsl:copy>
      <xsl:copy-of select="@*"/>
      <xsl:apply-templates/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="functions:*">
    <xsl:variable name="request_function">
      <xsl:value-of select="local-name(.)"/>
    </xsl:variable>
    <xsl:variable name="request_parameters">
      <xsl:for-each select="@*">
        <xsl:value-of select="concat('/', name(), '/', .)"/>
      </xsl:for-each>
    </xsl:variable>
    <xsl:variable name="rest_response" select="document(concat('http://foo.com/services/rest/', $request_function, $request_parameters) )"/>
    <xsl:apply-templates select="$rest_response/*/node()"/>
  </xsl:template>
</xsl:stylesheet>

Thanks!

Upvotes: 0

Dimitre Novatchev
Dimitre Novatchev

Reputation: 243489

Here is one possible pure XSLT 1.0 solution:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:functions="http://foo.com/api/rest"
 exclude-result-prefixes="functions">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:variable name="vDynPart">
  <xsl:for-each select="/*/functions:*/@*">
   <xsl:value-of select="concat('/', name(), '/', .)"/>
  </xsl:for-each>
 </xsl:variable>

 <xsl:variable name="vRes" select=
  "document(concat('http://foo.com/services/rest/fetch',
                   $vDynPart)
            )"/>

 <xsl:template match="node()|@*">
  <xsl:copy>
   <xsl:apply-templates select="node()|@*"/>
  </xsl:copy>
 </xsl:template>

 <xsl:template match="/">
  <xsl:copy>
   <xsl:copy-of select="@*"/>
   <xsl:apply-templates/>

   <xsl:apply-templates select="$vRes/*/node()"/>
  </xsl:copy>
 </xsl:template>

 <xsl:template match="functions:*"/>
</xsl:stylesheet>

Upvotes: 2

Related Questions