XSLT 1.0将namespace + xsi:type添加到元素

时间:2010-02-15 08:27:28

标签: xslt namespaces

我想离开这个:

<detail> 
 <BusinessError> 
   <environment>Test</environment> 
   <businesserror> 
      <BusinessCode>my_businesscode</BusinessCode> 
      <BusinessMessage>my_businessmessage</BusinessMessage> 
   </businesserror> 
  </BusinessError> 
 </detail> 

对此(只关注businesserror元素)

<detail> 
 <v1:BusinessError  xmlns:v1="ddd"> 
   <v1:environment>Test</v1:environment> 
   <v1:businesserror  xsi:type="ns2:AppErrorType" xmlns:ns2="aaaaa" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
     <ns2:BusinessCode>my_businesscode</ns2:BusinessCode> 
     <ns2:BusinessMessage>my_businessmessage</ns2:BusinessMessage> 
   </v1:businesserror> 
 </v1:BusinessError> 
</detail>

重要细节(我认为)命名空间uri是作为变量导入的!

我可以通过xs:属性添加xsi:type,并自动添加xsi名称空间 但不是命名空间(xmlns:ns2 =“aaaaa”)? 请注意,包含元素(businesserror)的名称空间与我尝试声明的名称(aaaa)不同(ddd)

感谢

3 个答案:

答案 0 :(得分:1)

此XSLT将命名空间定义添加到根元素(详细信息)。

<?xml version="1.0" encoding="utf-16"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                version="1.0"
                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                xmlns:ns2="aaaaa" xmlns:v1="ddd">
  <xsl:output omit-xml-declaration="yes" method="xml" version="1.0" />
  <xsl:template match="/">
    <xsl:apply-templates select="/detail" />
  </xsl:template>
  <xsl:template match="/detail">
    <detail>
      <xsl:element name="v1:BusinessError">
        <xsl:element name="v1:environment">
          <xsl:value-of select="BusinessError/environment/text()" />
        </xsl:element>
        <xsl:element name="v1:businesserror">
          <xsl:attribute name="xsi:type">ns2:AppErrorType</xsl:attribute>
          <xsl:element name="ns2:BusinessCode">
            <xsl:value-of select="BusinessError/businesserror/BusinessCode/text()" />
          </xsl:element>
          <xsl:element name="ns2:BusinessMessage">
            <xsl:value-of select="BusinessError/businesserror/BusinessMessage/text()" />
          </xsl:element>
        </xsl:element>
      </xsl:element>
    </detail>
  </xsl:template>
</xsl:stylesheet>

请勿更改&lt; detail&gt;节点到xsl:element节点,因为它不会通过命名空间定义进行传输。

答案 1 :(得分:0)

如果您希望动态创建命名空间,那么我认为您需要将XSLT 2.0与其xsl:namespace元素一起使用:

<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="2.0">

  <xsl:param name="v1" select="'ddd'"/>
  <xsl:param name="ns2" select="'aaaa'"/>

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

  <xsl:template match="BusinessError | environment">
    <xsl:element name="v1:{local-name()}" namespace="{$v1}">
      <xsl:apply-templates select="@* | node()"/>
    </xsl:element>
  </xsl:template>

  <xsl:template match="businesserror">
    <xsl:element name="v1:{local-name()}" namespace="{$v1}">
      <xsl:attribute name="xsi:type" namespace="http://www.w3.org/2001/XMLSchema-instance" select="'ns2:AppError'"/>
      <xsl:namespace name="ns2" select="$ns2"/>
      <xsl:apply-templates select="@* | node()"/>
    </xsl:element>
  </xsl:template>

  <xsl:template match="BusinessCode | BusinessMessage">
    <xsl:element name="ns2:{local-name()}" namespace="{$ns2}">
      <xsl:apply-templates select="@* | node()"/>
    </xsl:element>
  </xsl:template>

</xsl:stylesheet>

使用XSLT 1.0,您需要对样式表中的名称空间进行硬编码,然后将其复制:

<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:v1="ddd"
  xmlns:ns2="aaaa"
  version="1.0">

  <xsl:variable name="ns" select="document('')/xsl:stylesheet/namespace::*"/>

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

  <xsl:template match="BusinessError | environment">
    <xsl:element name="v1:{local-name()}" namespace="{$ns[local-name() = 'v1']}">
      <xsl:apply-templates select="@* | node()"/>
    </xsl:element>
  </xsl:template>

  <xsl:template match="businesserror">
    <xsl:element name="v1:{local-name()}" namespace="{$ns[local-name() = 'v1']}">
      <xsl:copy-of select="$ns[local-name() = 'ns2']"/>
      <xsl:attribute name="xsi:type" namespace="http://www.w3.org/2001/XMLSchema-instance">ns2:AppError</xsl:attribute>      
      <xsl:apply-templates select="@* | node()"/>
    </xsl:element>
  </xsl:template>

  <xsl:template match="BusinessCode | BusinessMessage">
    <xsl:element name="ns2:{local-name()}" namespace="{$ns[local-name() = 'ns2']}">
      <xsl:apply-templates select="@* | node()"/>
    </xsl:element>
  </xsl:template>

</xsl:stylesheet>

答案 2 :(得分:0)

如果你知道你的XSLT 1.0处理器支持像exsl:node-set这样的扩展函数,那么你可以按如下方式进行:

<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:exsl="http://exslt.org/common"
  version="1.0">

  <xsl:param name="v1" select="'ddd'"/>
  <xsl:param name="ns2" select="'aaaa'"/>

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

  <xsl:template match="BusinessError | environment">
    <xsl:element name="v1:{local-name()}" namespace="{$v1}">
      <xsl:apply-templates select="@* | node()"/>
    </xsl:element>
  </xsl:template>

  <xsl:template match="businesserror">
    <xsl:variable name="t1">
      <xsl:element name="ns2:foo" namespace="{$ns2}"/>
    </xsl:variable>
    <xsl:element name="v1:{local-name()}" namespace="{$v1}">
      <xsl:copy-of select="exsl:node-set($t1)/*/namespace::*[local-name() = 'ns2']"/>
      <xsl:attribute name="xsi:type" namespace="http://www.w3.org/2001/XMLSchema-instance">ns2:AppError</xsl:attribute>
      <xsl:apply-templates select="@* | node()"/>
    </xsl:element>
  </xsl:template>

  <xsl:template match="BusinessCode | BusinessMessage">
    <xsl:element name="ns2:{local-name()}" namespace="{$ns2}">
      <xsl:apply-templates select="@* | node()"/>
    </xsl:element>
  </xsl:template>

</xsl:stylesheet>