Index: main/trunk/greenstone3/web/interfaces/default/transform/gslib.xsl
===================================================================
--- main/trunk/greenstone3/web/interfaces/default/transform/gslib.xsl	(revision 34239)
+++ main/trunk/greenstone3/web/interfaces/default/transform/gslib.xsl	(revision 34240)
@@ -606,7 +606,42 @@
     <xsl:apply-templates select="pageResponse/collection|serviceCluster"/>
   </xsl:template>
-  
+
+  <!--
+      Solution to problem where incoming collection description contains HTML and we want to preserve
+      that HTML instead of XML's default behaviour stripping out all tags and just concatenating their text
+      content.
+      The actual solution is here:
+      https://stackoverflow.com/questions/19998180/xsl-copy-nodes-without-xmlns
+      - Close but adds namespacs to the first HTML tag:
+      https://stackoverflow.com/questions/6199345/how-to-copy-all-child-nodes-of-any-type-of-a-template-context-element
+      Other links that are a learning experience:
+      - https://support.microsoft.com/en-us/help/264665/how-to-display-html-in-xsl-style-sheet
+      (tags need to come in in entity form for xslt to remove the entities in output)
+      - https://forums.asp.net/t/1414309.aspx?Decoding+HTML+after+applying+an+XLST+transform+to+an+XML+control
+      (same problem)
+      - https://docs.oracle.com/javase/tutorial/jaxp/xslt/transformingXML.html
+      (general information)
+      - https://stackoverflow.com/questions/5876382/using-xslt-to-copy-all-nodes-in-xml-with-support-for-special-cases
+      (close to solution)
+  -->
   <xsl:template match="collection|serviceCluster">
-    <xsl:value-of select="displayItemList/displayItem[@name='description']" disable-output-escaping="yes"/>
+    <!-- original way: does not preserve html tags -->
+    <!--<xsl:value-of select="displayItemList/displayItem[@name='description']" disable-output-escaping="yes"/>-->    
+    <xsl:apply-templates select="displayItemList/displayItem[@name='description']"/>
+
+    <!-- Don't do this. It seems to remove any text nodes directly within this displayItem
+	 before copying only the subdnodes -->
+    <!-- <xsl:apply-templates select="displayItemList/displayItem[@name='description']/*" mode="copy-no-namespaces"/> -->
+
+     <!-- Don't do this: it will also copy the <displayItem> element itself into the HTML output -->
+     <!--<xsl:copy-of select="displayItemList/displayItem[@name='description']"/>-->
+     
+     <!-- The other way: requires the input to already be entity encoded for xslt to get it right,
+	  to get it ending up as tags in the HTML generated. An example of it working below.
+	  But that means we have to get the runtime code to send entity encoded elements, which
+	  is not what we want.
+     -->
+    <!--<xsl:text disable-output-escaping="yes">&lt;b&gt;hello&lt;/b&gt;</xsl:text>-->
+    
 <!-- Uncomment this section if you want the collection service links and their descriptions to appear -->
 	<!--<xsl:apply-templates select="serviceList">
@@ -614,5 +649,39 @@
     </xsl:apply-templates>-->
   </xsl:template>
-  
+
+  <!-- preserve any HTML tags *within* the collection description
+       Why is this adding an xmlns namespace to the first HTML tag encountered and converting
+       non html entities like the apostrophe character into their entity forms?
+       This seems to assume entities in the input should be converted:
+       https://stackoverflow.com/questions/31517944/xsl-disable-output-escaping-copy-of
+       But I'm wondering why when there's no entity in the input, copy-of produces entities
+       for chars like apostrophe in the output?
+       Note: there's xsl:copy and xsl:copy-of, we want copy-of!
+       - https://www.w3schools.com/xml/ref_xsl_el_copy.asp
+       - vs https://www.w3schools.com/XML/ref_xsl_el_copy-of.asp
+       
+       Info on avoiding doe/disable-output-escaping at https://saxonica.plan.io/issues/3214
+       https://stackoverflow.com/questions/31517944/xsl-disable-output-escaping-copy-of
+  -->
+  <xsl:template match="displayItem[@name='description']">
+    <!-- don't do this: it adds an xmlns namespace to the first/root html element in displayItem -->
+    <!--<xsl:copy-of select="node()"/>-->
+    <xsl:apply-templates select="node()" mode="copy-no-namespaces"/>
+   </xsl:template>
+   <!-- On mode attribute: https://www.w3schools.com/xml/ref_xsl_el_apply-templates.asp
+	https://stackoverflow.com/questions/4486869/can-one-give-me-the-example-for-mode-of-template-in-xsl
+	https://docs.microsoft.com/en-us/previous-versions/dotnet/netframework-4.0/ms256045(v=vs.100)?redirectedfrom=MSDN
+   -->
+   <xsl:template match="*" mode="copy-no-namespaces">
+     <xsl:element name="{local-name()}">
+       <xsl:copy-of select="@*"/>
+       <xsl:apply-templates select="node()" mode="copy-no-namespaces"/>
+     </xsl:element>
+   </xsl:template>
+   
+   <xsl:template match="comment()| processing-instruction()" mode="copy-no-namespaces">
+     <xsl:copy/>
+   </xsl:template>
+   
   <xsl:template match="serviceList">	
 	<xsl:param name="collName"/>
