使用XML模式在XML实例中指定默认命名空间

时间:2010-12-29 22:03:48

标签: xsd biztalk xml-namespaces biztalk-2009

我不确定它是否重要,但我正在使用BizTalk 2009来生成XML。

有没有办法在我的XML架构中指定生成的XML实例应该使用目标命名空间作为默认命名空间?

如果我有这样的xsd文件:

<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>

它创建一个这样的XML文件:

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

但我希望它能像这样创建一个XML文件:

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

我知道它们在技术上是等价的,但消费者(供应商API)的实施很差,我想给他们期望的东西。

4 个答案:

答案 0 :(得分:1)

我希望它取决于生成实例的软件,而不是模式。 XSD Schema是为了针对模式验证XML实例而开发的,而不是用于从中生成实例。所以它不太可能在XMLSchema中明确出现。但是,生成工具可能使用元素是(非)限定的事实

elementFormDefault="(un)qualified" 

触发前缀。

不完全在范围内,但以下内容值得阅读架构设计:http://www.xfront.com/HideVersusExpose.html

答案 1 :(得分:1)

一种方法是定义没有命名空间的模式。将BizTalk架构映射到没有命名空间的新定义的架构。从BizTalk的角度来看,您将拥有一个表示与消费者的实际合同的模式。 (即没有命名空间)此外,BizTalk使用命名空间#rootnodename来定义messageTypes。在此示例中,您将有两个模式

  1. somenamespace#somerootnodename
  2. #somerootnodename
  3. 这种方法的可能缺点是这会将此模式(#rootnodename)的使用限制为使用BizTalk组的1个实例。

答案 2 :(得分:1)

这是BizTalk使用此XML模式的默认行为,据我所知,没有内置方法可以更改它。

然而,您真正想要的是,出站消息符合比BizTalk使用的更清晰,更自由的格式。您可以通过使用自定义管道组件(和自定义发送管道)在传出消息离开BizTalk之前处理它。

我们的想法是更改名称空间前缀,作为在BizTalk外部发送邮件的一部分。转换发生在发送管道的处理过程中。

Nic Barden已发布博客并提供了一些源代码about this here。您可以使用他的示例作为执行名称空间前缀替换的基础,而不是替换名称空间本身。

我强烈建议您查看他在开发流媒体管道组件方面所做的所有帖子。 Nic已经做了大量而全面的工作,描述了编写健壮的企业级管道组件所需的所有内容。

答案 3 :(得分:1)

只要BizTalk btm映射邮件,就会添加ns0前缀。它不应该重要,因为它仍然是有效的xml,但是当向具有遗留或不完整的xml解析器的合作伙伴发送消息时,这可能是一个问题。

您可以删除ns0前缀,然后通过更改visual map to an .xslt map的btm,在输出消息上设置ns0默认命名空间。

e.g。将地图转换为xslt后,请更改xslt:

<?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>

要:

<?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>

即。更改默认的xmlns,然后自动删除ns0前缀。

更通用的解决方案也是可能的(例如类似于Firras'answer here),这可能是有用的,例如作为发送端口映射放置以从元素中去除所有前缀。但是,如果输出消息上有多个xmlns,则需要警惕!