在BizTalk中映射递归结构

时间:2013-03-26 19:30:27

标签: xslt mapping inline biztalk

我有以下XML

     <response>
       <Contacts>
         <Contact>
           <Name>John Doe</Name>
           <Age>48</Age>
           <DOB>
             <Day>12</Day>
             <Month>6</Month>
             <Year>1964</Year>
           </DOB>
           <Contacts>
             <Contact>
                <Name>Jane Walsh</Name>
                <Age>30</Age>
                <DOB>
                  <Day>24</Day>
                  <Month>3</Month>
                  <Year>1983</Year>
                </DOB>
             </Contact>
             <Contact>
               <Name>Rob Marsh</Name>
               <Age>55</Age>
               <DOB>
                 <Day>1</Day>
                 <Month>Feb</Month>
                 <Year>1958</Year>
               </DOB>
             </Contact>
           </Contacts>
         </Contact>
       </Contacts>
    </response>

我使用身份转换将结构复制到目标。

    <xsl:template name = "testTemplate" match="/*[local-name()='response']/*">
      <xsl:apply-templates mode="copy-no-ns" select="response"/>
    </xsl:template>
    <!-- Selectively mass copy some of the nodes without namespaces -->
    <xsl:template mode="copy-no-ns" match="*">
      <xsl:element name="{name(.)}" namespace="{namespace-uri(.)}">
        <xsl:copy-of select="@*"/>
        <xsl:apply-templates mode="copy-no-ns" select="node()"/>
      </xsl:element>
    </xsl:template>

XSL在Altova XMLSpy中工作,当我使用Visual Studio 2010测试它时产生所需的输出。但是BizTalk映射会产生如下的空节点(删除正确复制的其他内容)。

    <Contacts>
      <Contact>
        <Contacts>
          <Contact />
          <Contact />
        </Contacts>
      <Contact>
    </Contacts>

我不知道发生了什么以及如何解决这个问题。有什么建议?万分感谢

1 个答案:

答案 0 :(得分:4)

你明显的问题在于:

 <xsl:template name = "testTemplate" match="/*[local-name()='response']/*">
      <xsl:apply-templates mode="copy-no-ns" select="response"/>
 </xsl:template>

此模板匹配顶部元素response的任何子元素(在本例中只是名为Contacts的元素。

然后,它将模板应用于匹配的Contacts元素的所有子项,名为response但是,Contacts元素没有名为response 的子元素。此时,转换不能再产生任何输出。

最终结果只是

<response>


</response>

以下是完整转型

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:template match="node()|@*">
  <xsl:copy>
   <xsl:apply-templates select="node()|@*"/>
  </xsl:copy>
 </xsl:template>

 <xsl:template name = "testTemplate" match="/*[local-name()='response']/*">
      <xsl:apply-templates mode="copy-no-ns" select="response"/>
 </xsl:template>

    <!-- Selectively mass copy some of the nodes without namespaces -->
 <xsl:template mode="copy-no-ns" match="*">
   <xsl:element name="{name(.)}" namespace="{namespace-uri(.)}">
     <xsl:copy-of select="@*"/>
     <xsl:apply-templates mode="copy-no-ns" select="node()"/>
   </xsl:element>
 </xsl:template>
</xsl:stylesheet>

应用于提供的XML文档时:

<response>
    <Contacts>
        <Contact>
            <Name>John Doe</Name>
            <Age>48</Age>
            <DOB>
                <Day>12</Day>
                <Month>6</Month>
                <Year>1964</Year>
            </DOB>
            <Contacts>
                <Contact>
                    <Name>Jane Walsh</Name>
                    <Age>30</Age>
                    <DOB>
                        <Day>24</Day>
                        <Month>3</Month>
                        <Year>1983</Year>
                    </DOB>
                </Contact>
                <Contact>
                    <Name>Rob Marsh</Name>
                    <Age>55</Age>
                    <DOB>
                        <Day>1</Day>
                        <Month>Feb</Month>
                        <Year>1958</Year>
                    </DOB>
                </Contact>
            </Contacts>
        </Contact>
    </Contacts>
</response>

结果如上所述:

<response>


</response>

<强>解决方案

只需替换

<xsl:apply-templates mode="copy-no-ns" select="response"/>

<强>与

<xsl:apply-templates mode="copy-no-ns" select="node()"/>

完整转化

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="node()|@*">
  <xsl:copy>
   <xsl:apply-templates select="node()|@*"/>
  </xsl:copy>
 </xsl:template>

 <xsl:template name = "testTemplate" match="/*[local-name()='response']/*">
      <xsl:apply-templates mode="copy-no-ns" select="node()"/>
 </xsl:template>

    <!-- Selectively mass copy some of the nodes without namespaces -->
 <xsl:template mode="copy-no-ns" match="*">
   <xsl:element name="{name(.)}" namespace="{namespace-uri(.)}">
     <xsl:copy-of select="@*"/>
     <xsl:apply-templates mode="copy-no-ns" select="node()"/>
   </xsl:element>
 </xsl:template>
</xsl:stylesheet>

在提供的XML文档(上面)上应用此转换时,生成所需结果

<response>
   <Contact>
      <Name>John Doe</Name>
      <Age>48</Age>
      <DOB>
         <Day>12</Day>
         <Month>6</Month>
         <Year>1964</Year>
      </DOB>
      <Contacts>
         <Contact>
            <Name>Jane Walsh</Name>
            <Age>30</Age>
            <DOB>
               <Day>24</Day>
               <Month>3</Month>
               <Year>1983</Year>
            </DOB>
         </Contact>
         <Contact>
            <Name>Rob Marsh</Name>
            <Age>55</Age>
            <DOB>
               <Day>1</Day>
               <Month>Feb</Month>
               <Year>1958</Year>
            </DOB>
         </Contact>
      </Contacts>
   </Contact>
</response>

请注意

此转换假定元素没有属性。如果此假设不成立,则转换会在具有属性的任何XML文档上产生错误的结果。可以提供正确且更通用的转换,但我相信这就是您所要求的。