简体   繁体   中英

Cannot dynamically create namespace node for xsi:type attribute

Assume

<myDoc xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
       xmlns:js="urn:myJS1"
       xmlns:ns="urn:myNS1">
   <myElem1  xsi:type="ns:myComplexType"/>
   <myElem2 xsi:type="js:myComplexType"/>
</myDoc>

I want to migrate this doc to use version 2 of the namespaces but need to do this dynamically because I can't predict which values of xsi:type are in the instance. Also ideally I want the same prefixes. So I want something like

<myDoc xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
   <myElem1  xmlns:ns="newNs" xsi:type="ns:myComplexType"/>
   <myElem2 xmlns:js="newNs" xsi:type="js:myComplexType"/>
</myDoc>

My best effort intercepts the creation of the xsi:type attribute and tries to create a namespace node for the new version. It is not working.

   <?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
version="2.0">

    <xsl:variable name="schemas">
        <thing targetNamespace="newNs"/>
    </xsl:variable> 

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


     <xsl:template match="@xsi:type">
      <xsl:copy copy-namespaces="no">       
         <xsl:namespace name="{substring-before(.,':')}" select="$schemas/thing/@targetNamespace"/>
         <xsl:next-match/>       
      </xsl:copy>
   </xsl:template>

</xsl:stylesheet>

but this does not result in an instance showing the new namespace nodes.

Although my example is XSLT 2.0, an XSLT 3.0 solution to this is fine.

In the match="@xsi:type" template, the context node is the @xsi:type attribute itself, so selecting @xsi:type is wrong, it should simply be . .

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
version="2.0">

    <xsl:variable name="schemas">
        <thing targetNamespace="newNs"/>
    </xsl:variable> 

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


     <xsl:template match="@xsi:type">
         <xsl:namespace name="{substring-before(.,':')}" select="$schemas/thing/@targetNamespace"/>
         <xsl:next-match/>       
   </xsl:template>

</xsl:stylesheet>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM