Tuesday, August 02, 2011

BizTalk Map - Copy Node containing HTML

I recently had to map data from an InfoPath 2007 form to a canonical schema. The input from InfoPath usually contained HTML, although on occasion it contained encoded HTML (depending on where the original data was pulled from). The output needed to be in a CDATA section so that it could be treated as plain old text.

After consulting several people at work and looking at lots of blog posts, I was able to pull off a solution. I'm sure there are ways to improve the quality of the code, but it does work. One thing I don't like about this solution is that it adds a namespace attribute to the top level HTML nodes. Fortunately every browser I tested with ignores the namespace.

Here's the source schema:


And here's the contents of the Inline XSLT functoid that I used:

<xsl:element name="ns0:FreeformData1" >
<xsl:text disable-output-escaping="yes">&lt;![CDATA[</xsl:text>
<xsl:choose>
<xsl:when test="count(/*[local-name()='myFields']/*[local-name()='FreeData1']/child::*/child::node()) &gt; 0">
<xsl:for-each select = "/*[local-name()='myFields']/*[local-name()='FreeData1']/child::node()">
<xsl:copy-of select="self::*" />
</xsl:for-each>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="string(/*[local-name()='myFields']/*[local-name()='FreeData1'])" disable-output-escaping="yes"/>
</xsl:otherwise>
</xsl:choose>
<xsl:text disable-output-escaping="yes">]]&gt;</xsl:text>
</xsl:element>

If the input XML looks like this:

<ns0:myFields xmlns:ns0="http://sampleforblog.namespace.com">
<ns0:field1>Test data</ns0:field1>
<ns0:FreeData1><html><FONT color="#ff0000">Hello</FONT> world this <STRONG>is a test</STRONG></html></ns0:FreeData1>
</ns0:myFields>


Then the output XML looks like this:

<ns0:yourFields xmlns:ns0="http://sample2forblog">
<ns0:field>Test data</ns0:field>
<ns0:FreeformData1><![CDATA[<html xmlns:ns0="http://sampleforblog.namespace.com"><FONT color="#ff0000">Hello</FONT> world this <STRONG>is a test</STRONG></html>]]></ns0:FreeformData1>
</ns0:yourFields>

I'm not showing the case where the HTML is encoded, but I did test that as well. Encoded HTML is handled by the "otherwise" case in the XSLT above.

1 comment:

Jonas Katona said...

Your post was very helpful, thx