Dealing with cXML based messages in BizTalk
November 29th, 2007cXML (commerce eXtensible Markup Language) is a XML based standard for communication of data related to electronic commerce. The problem from a BizTalk perspective is that they don’t publish any XML schemas (XSD), only Document Type Definition (DTD).
When trying to generate a schema based on a DTD using the functionality in BizTalk (via Add Generated Items) one ends up with a schema split of three files that really doesn’t make any sense (XmlSpy doesn’t do a very good job either …). So after a while I found Nick Heppleston schema repository! After some tweaking I actually had a cXML Order schema in the version I was looking for! Thanks Nick!
The next set of problems was to handle the lack of XML namespace and the DOCTYPE declaration that messages validating against DTD carries on top.
<?xml version="1.0" standalone="no"?> <!DOCTYPE cXML SYSTEM "http://xml.cxml.org/schemas/cXML/1.2.014/cXML.dtd"> <cXML xml:lang="en-US" payloadID="2007117.25919@Contempus" timestamp="2007-11-07T11:06:16+01:00">
To handel these two issues I set up a receive pipeline that looked like the one below.
Remove the DOCTYPE declaration
First I created a pipeline component to remove the DOCTYPE node. It’s simple code using regular expression to find the DOCTYPE node, replace it with an empty string and return the message.
public IBaseMessage Execute(IPipelineContext pc, IBaseMessage inmsg) { string messageString = new StreamReader(inmsg.BodyPart.Data).ReadToEnd(); Regex doctypePattern = new Regex("<!DOCTYPE.+?>"); messageString = doctypePattern.Replace(messageString, string.Empty); MemoryStream memStream = new MemoryStream(); byte[] data = Encoding.UTF8.GetBytes(messageString); memStream.Write(data, 0, data.Length); memStream.Seek(0, SeekOrigin.Begin); inmsg.BodyPart.Data = memStream; return inmsg; }
Set an XML namespace
Secondly I used Richard Seroter’s post on how to change the SetNSForMsg component to add a XML namespace. That’s the second component showing in the decode stage of the pipeline.
Arrow number 3 shows how the SetMsgNS exposes a property that allows us to set the namespace that we can configure per pipeline. In this case I’ve set it to http://schemas.modhul.com/cXML/1.2.014/OrderRequest which is the namespace of the cXML schema I’m currently working agains.
In the end we’ll have a message with the following declaration and root node.
<?xml version="1.0" encoding="utf-16" standalone="no"?> <cXML xml:lang="en-US" payloadID="2007117.25919@Contempus" xmlns="http://schemas.modhul.com/cXML/1.2.014/OrderRequest" timestamp="2007-11-07T11:06:16+01:00">
Now we’re ready to start mapping!
November 30th, 2007 at 10:51 am
Hey Richard, pleased that the cXML schema was of use – your scenario was exactly why I added the schemas to my website (I’m actually quite surprised that the cXML working group haven’t released a cXML XSD, given that DTD’s are now depreciated).
Nick.
November 30th, 2007 at 2:34 pm
@Nick: Yes, it’s very strange they haven’t updated that. Your work saved me many hours. Thanks again!
November 30th, 2007 at 2:54 pm
Hi Richard, great post.
The only thing I would say, at the risk of stating the obvious, is that the code you’ve posted reads the entire message to memory in order to run the regex to remove the DTD declaration.
This is not necessarily a problem for small messages, or for a low volume of messages, but is not best practice.
It might be worth taking the extra day or two it should take to write it in a streaming fashion so that you don’t actually have to read the message at all.
December 1st, 2007 at 10:06 am
@Yossi: Great comment. I considered that but in this case I know the message size and I have a rough idea of the volume that I’ll receive. Based on that I decided to make it as simple as possible for now. If I however should be fully able to reuse this in any scenario I really should try and get to that. That’ll be my next post
February 10th, 2009 at 7:14 am
Richard,
I have used same xsd for validating example xml comes with cXML but my validator serves me an error, I will really thankfull to you if you can share your xsd to save my time.