20
Dec

Removing namespace from outgoing messages

Way to often I get a request to deliver a message from BizTalk without any XML namespace. Comments like the one below aren’t that rare.

Why do you put those "ns0" I front of every tag!? We can’t read the XML when it’s written like that! All our XPath and XSLT seems to fail.

We don’t want <ns0:OutMessage xmlns:ns0="Acme.Messages.OutMessage/1.0"> … We expect the messages from you to be like <OutMessage>

Is that some BizTalk specific?

I always try to explain what XML namespaces are, and why it’s a good idea to use them (especially when it comes to versioning of messages). Sometimes it’s just impossible to get people to understand the advantages of using it and to persuade them to change their solutions to handle XML namespaces. It’s in these cases it’ll be up to the implementation in BizTalk to remove the namespace.

How to remove XML namespace

There are a couple of ways of achieving this, we can use .NET code that we call in a pipeline or in an orchestration. But we can also handle this using XSL – and that’s what I’ll show in this post. The XSL stylesheet below will remove all XML namespaces while transforming the message. Basically it just copies the nodes, attributes and it’s values using the local-name() function to ignore the XML namespaces.

<?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/"> <xsl:copy> <xsl:apply-templates /> </xsl:copy> </xsl:template> <xsl:template match="*"> <xsl:element name="{local-name()}"> <xsl:apply-templates select="@* | node()" /> </xsl:element> </xsl:template> <xsl:template match="@*"> <xsl:attribute name="{local-name()}"> <xsl:value-of select="."/> </xsl:attribute> </xsl:template> <xsl:template match="text() | processing-instruction() | comment()"> <xsl:copy /> </xsl:template> </xsl:stylesheet>

Apply the XSL transformation

We can use this XSL stylesheet in a ordinary BizTalk map on the send port using the Custom XSL Path property in the BizTalk Mapper. The result is that the XSL we usually generate in the mapping tool will be overridden by our own XSL stylesheet. The figure below shows how we use the property windows of the grid in the BizTalk Mapper to set the property and point the Mapper to our XSLT document.

But what if we already have a map on the send port and it’s that already transformed message we like to remove the namespace from? One possibility is to use the XSLT Transform pipeline component that comes with the BizTalk 2006 SDK. It’s usually located at C:\Program Files\Microsoft BizTalk Server 2006\SDK\Samples\Pipelines\XslTransformComponent\XslTransform on your development machine. I’ve written about this sample component before here were I used it another scenario.

The figure below shows how we use the property windows of the XSLT Transform Component in a pipeline in the Pipeline designer tool to set the path to our XSLT stylesheet.

Final thoughts

The XSLT Transform component is far from perfect and the obvious problem is of course that the component loads the whole message into memory using the XmlDocument class to read the message. That means that this solution isn’t for those scenarios where you’ll have huge messages coming in by the thousands. But for those cases where you have normal sized messages and you have a idea of the traffic you receive, it’s a quick and easy solution.

Any comments on the pro and cons on this solution and how you usually solve this scenario will be appreciated!

UPDATE #1: Make sure you don’t miss Johan Hedbergs solution to this problem. Basically he solved it using the Microsoft.BizTalk.Streaming.dll which will give you  better memory management.

UPDATE #2: Based on the comments to this post I’ve posted an "updated" post here solving this using ordinary mapping and defining a schema without a XML namespace – easier and more correct.

There's 12 Comments So Far

  • Johan Hedberg
    January 8th, 2008 at 1:29 am

    My main objection to the xslt map solution would be that you would most likely want to do this on your outgoing xml, which as you mentions might interfere with the map on the sendport. Thus I’d prefer a pipeline solution. Building such I’d like one that I can use for any file I wish to send through (ie without loading data into memory if I can help it), because you never know when that agreed upon 1MB turns out to have become 15MB. I’d go for a custom pipeline component using the XmlTransformStream. I’ve explained this implementation in a blogpost at http://blogical.se/blogs/johan/archive/2008/01/07/removing-xml-namespace-in-a-pipeline-component.aspx. Although it’s more limited in it’s uses then the XslTransformComponent, I feel it’s more suited for this scenario.

  • Jeff Lynch
    June 16th, 2008 at 10:24 pm

    I’m a little confused. Why wouldn’t you just create an outbound schema with the elementFormDefault set to “unqualified” or aaatributeFormDefault set to “unqualified” and map to this schema?

  • Richard
    June 17th, 2008 at 7:36 am

    Hi Jeff,

    Setting the elementFormDefault attribute tells XSD that all globally declared elements (root node) has to live inside of a namespace (prefix or default). Locally declared element however don’t have to exists within a namespace. There isn’t built-in functionality to totally strip a message of it’s namespace as this generally speaking is wrong – if you have a language on the receiving side that understands XML and have a correct implementation of XML, XML namespaces isn’t a problem. Totally removing XML namespace would also make the XML message useless to BizTalk as BizTalk (as you know) uses the namespace in combination with the name of the root node to actually understand what kind of message it is.

    Hope that explains it and sorry for pointing out a couple of obvious things.

    I usually recommend this article when it comes to XML namespaces: http://www.oracle.com/technology/pub/articles/srivastava_namespaces.html
    Also make sure yo don’t miss Johans solution using streaming, you’ll find it here: http://blogical.se/blogs/johan/archive/2008/01/07/removing-xml-namespace-in-a-pipeline-component.aspx

  • Jeff Lynch
    June 18th, 2008 at 2:52 am

    Richard,

    That’s odd because I’ve been using BizTalk Server for the past ten years (yes, 10 years) and several of our trading partners still running BizTalk Server 2002 and 2004 require the use of XML 1.0 documents that do NOT use namespaces, namespace prefixes or even the xml declaration.

    For example, this is a perfectly acceptable XML 1.0 document:

    1234567

    And BizTalk Server 2006 can certainly be made to parse and serialize xml documents like this. BizTalk does NOT require the use of a namespace although by default the XML parser uses the namespace and root node name to identify an inbound document. If the namespace is missing, the root node name must be unique in the deployed schema assembly.

    I’d be happy to send you a copy of a current BizTalk Server 2006 R2 solution that both parses and serializes xml documents like this all the time. In fact, I’ve processed thousands and thousands of such documents in just the past twelve months alone.

  • Jeff Lynch
    June 18th, 2008 at 2:53 am

    Sorry about that. Your software seems to have stripped out my xml from the previous comment.

  • Richard
    June 26th, 2008 at 8:35 am

    Hi again Jeff,

    I misunderstood a couple of thing. In your first comment I didn’t get that you actually meant defining a schema without a XML namespace. Then I said that a schema without a XML namespace is useless to BizTalk which of course is wrong. I should have phrased that differently.

    Anyway. Great comment. Thanks. I’ve posted an “update” to this post here: http://www.richardhallgren.com/removing-xml-namespaces-revisit/

  • Mick
    September 2nd, 2008 at 1:07 pm

    Being a .NET & Biztalk developer I’m quite familiar with XML (and XPATH) – but not with XSLT. So I’m on a quest to understand XSLT better :-)

    One thing I find somewhat confusing is how & when the different apply-templates are executed (in sequence or “parallel” somehow or…?).

    I would be grateful if somebody could explain what is being executed when (and why this is so)? Maybe a short step-by-step walkthrough :-)

    Thanks in advance.

    / Mick

  • Richard
    September 2nd, 2008 at 1:19 pm

    @Mick

    Apply-templates are applied on “match” (that is if you don’t have a “mode” in there).

    Say several templates are matching the node you select when you apply-templates all of them will execute … In the example in this post all templates will match and execute but on different part of the node set I select in the apply-templates.

    I hope that makes some sense. XSLT is so powerful and a must understand for any BizTalk developer. It’s however very “different” …

  • car jacks
    March 14th, 2009 at 1:48 pm

    I must say, I can not agree with you in 100%, but it’s just my opinion, which indeed could be very wrong.
    p.s. You have a very good template for your blog. Where have you got it from?

  • sandrar
    September 10th, 2009 at 10:44 pm

    Hi! I was surfing and found your blog post… nice! I love your blog. :) Cheers! Sandra. R.

Who Linked To This Post?

  1. Removing Xml Namespace in a pipeline component - Be Logical - writings by Johan Hedberg
  2.   Removing XML namespaces - revisit by .RICHARD

Share your thoughts, leave a comment!