1

I'm not sure if it matters, but I'm using BizTalk 2009 to generate the XML.

Is there a way to specify in my XML schema that the generated XML instance should use the target namespace as the default namespace?

If I have an xsd file like this:

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
           targetNamespace="http://example.com/">
  <xs:element name="example">
    <xs:complexType>
      <xs:attribute name="value" type="xs:string" /> 
    </xs:complexType>
  </xs:element>
</xs:schema>

It creates an XML file like this:

<ns0:example value="something" xmlns:ns0="http://example.com/" />

But I want it to create an XML file like this:

<example value="something" xmlns="http://example.com/" />

I know that they're technically equivalent, but the consumers (vendor APIs) are poorly implemented and I'd like to give them what they expect.

4 Answers 4

1

I would expect that it depends on the software generating the instance, not the schema. XSD Schema was developed for validation of XML instances against a schema, not for generating instances from it. So it is unlikely to be present explicitly in XMLSchema. The generating tools might, however, use the fact that elements were (un)qualified

elementFormDefault="(un)qualified" 

to trigger the prefixing.

Not completely in scope, but the following is worth reading for schema design: http://www.xfront.com/HideVersusExpose.html

1

One way would be to define a schema without the namespace. Map the BizTalk schema to the newly defined schema without namespace. From a BizTalk viewpoint, you would have a schema which represents the actual contract with the consumers. (i.e. without namespaces) Also, BizTalk uses namespace#rootnodename to define messageTypes. In this example, you would have two schemas

  1. somenamespace#somerootnodename
  2. #somerootnodename

The possible drawbacks of this approach are this would limiting the usage of this schema (#rootnodename) to 1 instance with the BizTalk group.

1

This is the default behaviour of BizTalk working this XML schemas and, as far as I know, there is no builtin way to change this.

What you really want, however, is that outbound messages conform to a cleaner and more liberal format than what is used by BizTalk. You can do this by using a custom pipeline component (and a custom send pipeline) to process the outgoing message before it leaves BizTalk.

The idea is to change the namespace prefix as part of sending the message outside BizTalk. The transformation happens during the processing of the send pipeline.

Nic Barden has blogged and provided some source code about this here. You can use his sample as the basis for performing replacement of namespace prefixes, rather than replacing namespaces themselves.

I strongly encourage you to check out the whole series of posts he's done about Developing Streaming Pipeline Components. Nic has made an extensive and thorough job of describing all that's needed to author robust and enterprise-class pipeline components.

1
  • Please, let me know if you need help setting up such a custom pipeline component. Commented Jan 3, 2011 at 11:19
0

The ns0 prefix is added whenever a BizTalk btm maps a message. It shouldn't matter as this is still valid xml, however this could be a problem when sending messages to partners with legacy or incomplete xml parsers.

You can remove the ns0 prefix and instead make ns0 your default namespace on the output message by changing your btm from a visual map to an .xslt map.

e.g. Once you have converted your map to xslt, change the xslt from:

<?xml version="1.0" encoding="utf-16"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:msxsl="urn:schemas-microsoft-com:xslt"
                exclude-result-prefixes="msxsl s0"
                version="1.0"
                xmlns:ns0="http://targetns"
                xmlns:s0="http://sourcens"
                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <xsl:output omit-xml-declaration="yes" method="xml" version="1.0" />
  <xsl:template match="/">
    <xsl:apply-templates select="s0:FromRoot" />
  </xsl:template>
  <xsl:template match="s0:FromRoot">
    <ns0:ToRoot>
      <xsl:for-each select="s0:FromElement">
        <ns0:ToElement>
          <xsl:value-of select="text()"/>
        </ns0:ToElement>
      </xsl:for-each>
    </ns0:ToRoot>
  </xsl:template>
</xsl:stylesheet>

To:

<?xml version="1.0" encoding="utf-16"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:msxsl="urn:schemas-microsoft-com:xslt"
                xmlns:var="http://schemas.microsoft.com/BizTalk/2003/var"
                exclude-result-prefixes="msxsl s0"
                version="1.0"
                xmlns="http://targetns"
                xmlns:s0="http://sourcens"
                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <xsl:output omit-xml-declaration="yes" method="xml" version="1.0" />
  <xsl:template match="/">
    <xsl:apply-templates select="s0:FromRoot" />
  </xsl:template>
  <xsl:template match="s0:FromRoot">
    <ToRoot>
      <xsl:for-each select="s0:FromElement">
        <ToElement>
          <xsl:value-of select="text()"/>
        </ToElement>
      </xsl:for-each>
    </ToRoot>
  </xsl:template>
</xsl:stylesheet>

i.e. change the default xmlns and then remove the ns0 prefixes automatically.

A more generic solution is also possible (e.g. similar to Firras' answer here), which could be useful e.g. to place as a send port map to strip out all prefixes from elements. However, one needs to be wary if there are more than one xmlns on the output message!

Not the answer you're looking for? Browse other questions tagged or ask your own question.