satsamsk
satsamsk

Reputation: 67

display self closing xml elements to html output

My requirement is to display some xml elements (which are a part of input xml) in an html page.

for eg:

<org:specs>
  <org:wild animal="6" species="land"/>
  <org:fish animal="7" species="water"/>
  <org:bird animal="8" species="trees"/>
  <org:mammal animal="9" species="land"/>
</org:specs>

I want this entire xml snippet to appear as it is in the html output page, retaining the indentation followed in the input Anyone has any idea on how to implement it using XSLT or Xquery?

EDIT: Jan 2nd, 2012

I tried the first solution(given below). It works, but i lost the indentation. Giving more details, the implementation in my case will be using Xquery. I will use Marklogic command xdmp:xslt-eval(<Stylesheet>,<A-Xquery-function-retrieving-the-above-xml>). When I use the first solution, the resulting html page has no indentation

Upvotes: 0

Views: 691

Answers (3)

derickson
derickson

Reputation: 305

Depending on the browser, HTML doesn't preserve white space very well unless you start doing CSS, which isn't supported uniformly in browsers. I do the following, which preserves white space on display and in the character serialization:

xquery version "1.0-ml";

declare namespace org = "someorg";

let $xml := 
<org:specs>
  <org:wild animal="6" species="land"/>
  <org:fish animal="7" species="water"/>
  <org:bird animal="8" species="trees"/>
  <org:mammal animal="9" species="land"/>
</org:specs>


let $quote-options :=
<options xmlns="xdmp:quote">
  <method>xml</method>
  <indent>yes</indent>
  <indent-untyped>yes</indent-untyped>
</options>

return

<div><pre>
{xdmp:quote($xml, $quote-options)}
</pre></div>

Upvotes: 2

grtjn
grtjn

Reputation: 20414

The following works like a charm in MarkLogic CQ, using (an old) FireFox:

let $xml :=
<org:specs xmlns:org="some:org"> 
  <org:wild animal="6" species="land"/> 
  <org:fish animal="7" species="water"/> 
  <org:bird animal="8" species="trees"/> 
  <org:mammal animal="9" species="land"/> 
</org:specs> 

return

<html><body>
<h1>Org</h1>

<xmp>{$xml}</xmp>

</body>
</html>

Not sure the xmp tag is supported by all browsers yet though. I used to take the 'textify' approach (putting it in a pre without the br tags) as suggested by Dimitre.

Upvotes: 0

Dimitre Novatchev
Dimitre Novatchev

Reputation: 243529

I. An easy way:

This transformation:

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

 <xsl:template match="org:specs">
     <xmp>
       <xsl:copy-of select="."/>
     </xmp>
 </xsl:template>
</xsl:stylesheet>

when applied on this XML document (the provided non-well-formed text made an well-formed XML document):

<t xmlns:org="some:org">
<org:specs>
  <org:wild animal="6" species="land"/>
  <org:fish animal="7" species="water"/>
  <org:bird animal="8" species="trees"/>
  <org:mammal animal="9" species="land"/>
</org:specs>
</t>

produces:

<xmp>
   <org:specs xmlns:org="some:org">
      <org:wild animal="6" species="land"/>
      <org:fish animal="7" species="water"/>
      <org:bird animal="8" species="trees"/>
      <org:mammal animal="9" species="land"/>
   </org:specs>
</xmp>

and this displays in the browser in the wanted way:

<org:specs xmlns:org="some:org">
  <org:wild animal="6" species="land"/>
  <org:fish animal="7" species="water"/>
  <org:bird animal="8" species="trees"/>
  <org:mammal animal="9" species="land"/>
</org:specs>

II. Prety-looking, browser-displayed XML

See the XSLT code of the XPath Visualizer how this application produces such result.

III. Generating all the required input for the browser as text (method="text"):

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="text" encoding="utf-8"/>

 <xsl:template match="/*">
  <xsl:apply-templates select="*[1]" mode="textify"/>
 </xsl:template>

 <xsl:template match="*/*[*]" mode="textify">
         <xsl:text>&amp;lt;</xsl:text>
          <xsl:value-of select="name()"/>

   <xsl:apply-templates select="@*" mode="textify"/>
   <xsl:text>></xsl:text>
   <xsl:apply-templates select="*|text()" mode="textify"/>

         <xsl:text>&amp;lt;/</xsl:text>
          <xsl:value-of select="name()"/>
   <xsl:text>></xsl:text>
 </xsl:template>

 <xsl:template match="*/*[not(node())]" mode="textify">
         <xsl:text>&amp;lt;</xsl:text>
          <xsl:value-of select="name()"/>

   <xsl:apply-templates select="@*" mode="textify"/>
   <xsl:text>/></xsl:text>
 </xsl:template>

 <xsl:template match="@*" mode="textify">
  <xsl:text> </xsl:text>
  <xsl:value-of select="name()"/>
  <xsl:text>="</xsl:text>
  <xsl:value-of select="."/>
  <xsl:text>"</xsl:text>
 </xsl:template>

 <xsl:template match="text()" mode="textify">
  <xsl:call-template name="textify">
   <xsl:with-param name="pText" select="."/>
  </xsl:call-template>
 </xsl:template>

 <xsl:template name="textify">
  <xsl:param name="pText"/>

  <xsl:if test="string-length($pText) >0">
   <xsl:variable name="vChar" select="substring($pText,1,1)"/>
    <xsl:choose>
     <xsl:when test="$vChar = ' '">
       <xsl:value-of select="'&amp;#xA0;'"/>
     </xsl:when>
     <xsl:when test="$vChar = '&#9;'">
       <xsl:value-of select="'&amp;#xA0;&amp;#xA0;'"/>
     </xsl:when>
     <xsl:when test="$vChar = '&#xA;'">
       <xsl:value-of select="'&lt;br />'"/>
     </xsl:when>
     <xsl:otherwise>
      <xsl:value-of select="$vChar"/>
     </xsl:otherwise>
    </xsl:choose>
  <xsl:call-template name="textify">
   <xsl:with-param name="pText" select=
    "substring($pText, 2)"/>
  </xsl:call-template>
  </xsl:if>
 </xsl:template>

</xsl:stylesheet>

when this transformation is applied on the same XML document (above), it produces the wanted result:

&lt;org:specs><br />&#xA0;&#xA0;&lt;org:wild animal="6" species="land"/><br />&#xA0;&#xA0;&lt;org:fish animal="7" species="water"/><br />&#xA0;&#xA0;&lt;org:bird animal="8" species="trees"/><br />&#xA0;&#xA0;&lt;org:mammal animal="9" species="land"/><br />&lt;/org:specs>

and it is displayed by the browser as:

<org:specs>
  <org:wild animal="6" species="land"/>
  <org:fish animal="7" species="water"/>
  <org:bird animal="8" species="trees"/>
  <org:mammal animal="9" species="land"/>
</org:specs>

Upvotes: 4

Related Questions