1
votes

I had to upgrade my XSL stylesheet namespace which I use for "cleaning" an ADO XML from http://www.w3.org/TR/WD-xsl to http://www.w3.org/1999/XSL/Transform - and now using that stylesheet does not provide the same output as before, therefore breaking functionality.

I've tried a number of combinations but none of them are providing the same result as before - I'm new to XSL. Can you please help?

I'm using MSXML2.DOMDocument60.transformNodeToObject as API in VB to apply the stylesheet.

Here is my input ADO XML:

<xml xmlns:s="uuid:BDC6E3F0-6DA3-11d1-A2A3-00AA00C14882"
xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882"
xmlns:rs="urn:schemas-microsoft-com:rowset"
xmlns:z="#RowsetSchema">
  <s:Schema id="RowsetSchema">
    <s:ElementType name="row" content="eltOnly" rs:updatable="true">
      <s:AttributeType name="ShipperID" rs:number="1"
        rs:basetable="shippers" rs:basecolumn="ShipperID"
        rs:keycolumn="true">
        <s:datatype dt:type="int" dt:maxLength="4" rs:precision="10"
          rs:fixedlength="true" rs:maybenull="false"/>
      </s:AttributeType>
      <s:AttributeType name="CompanyName" rs:number="2"
        rs:nullable="true" rs:write="true" rs:basetable="shippers"
        rs:basecolumn="CompanyName">
        <s:datatype dt:type="string" dt:maxLength="40" />
      </s:AttributeType>
      <s:AttributeType name="Phone" rs:number="3" rs:nullable="true"
        rs:write="true" rs:basetable="shippers"
        rs:basecolumn="Phone">
        <s:datatype dt:type="string" dt:maxLength="24"/>
      </s:AttributeType>
      <s:extends type="rs:rowbase"/>
    </s:ElementType>
  </s:Schema>
  <rs:data>
    <rs:insert>
      <z:row ShipperID="1" CompanyName="Speedy Express" Phone="(503) 111-4567"/>
      <z:row ShipperID="2" CompanyName="United Package" Phone="(503) 222-4567"/>
      <z:row ShipperID="3" CompanyName="Federal Shipping" Phone="(503) 333-4567"/>
    </rs:insert>
  </rs:data>
</xml>

Here is the old stylesheet that worked:

<?xml version='1.0'?>                                       
<stylesheet xmlns='http://www.w3.org/TR/WD-xsl'>
  <template>
    <copy>
      <apply-templates select="@* | * | comment() | pi() | text()"/>
    </copy>
  </template>
  <template match="rs:insert" >
    <apply-templates select="@* | * | comment() | pi() | text()"/>
  </template>
  <template match="rs:data" >
    <element name="data">
      <apply-templates select="@* | * | comment() | pi() | text()"/>
    </element>
  </template>
  <template match="z:row" >
    <element name="row">
      <apply-templates select="@* | * | comment() | pi() | text()"/>
    </element>
  </template>
  <template match="@rs:forcenull" >
    <attribute name="forcenull"/>
  </template>
  <template match="s:Schema" />
  <template match="@xmlns:s" />
  <template match="@xmlns:dt" />
  <template match="@xmlns:rs" />
  <template match="@xmlns:z" />
</stylesheet>

Here is the result I got before and ALSO what I need now:

<xml>
  <data>
      <row ShipperID="1" CompanyName="Speedy Express" Phone="(503) 111-4567"></row>
      <row ShipperID="2" CompanyName="United Package" Phone="(503) 222-4567"></row>
      <row ShipperID="3" CompanyName="Federal Shipping" Phone="(503) 333-4567"></row>
  </data>
</xml>

And here is the new stylesheet (work in progress):

<?xml version="1.0" encoding="UTF-8"?>
<stylesheet xmlns="http://www.w3.org/1999/XSL/Transform" version = "3.0"
 xmlns:rs="urn:schemas-microsoft-com:rowset" xmlns:z="#RowsetSchema">
  <template match="/">
    <copy>
      <apply-templates select="@* | * | comment() | processing-instruction() | text()" />
    </copy>
  </template>
  <template match="rs:insert">
      <apply-templates select="@* | * | comment() | processing-instruction() | text()"/>
  </template>
  <template match="rs:data">
    <element name="data">
      <apply-templates select="@* | * | comment() | processing-instruction() | text()"/>
    </element>
  </template>
  <template match="z:row">
    <element name="row">
      <copy-of select="@* | * | comment() | processing-instruction() | text()"/>
    </element>
  </template>
  <template match="@rs:forcenull" >
    <attribute name="forcenull"/>
  </template>
  <template match="s:Schema"/>
  <template match="@xmlns:s"/>
  <template match="@xmlns:dt"/>
  <template match="@xmlns:rs"/>
  <template match="@xmlns:z"/>
</stylesheet>

And here is what I get now as result (wrong, not 100% same as before):

<?xml version="1.0" encoding="UTF-16"?>
<data xmlns="http://www.w3.org/1999/XSL/Transform">
  <row ShipperID="1" CompanyName="Speedy Express" Phone="(503) 111-4567"></row>
  <row ShipperID="2" CompanyName="United Package" Phone="(503) 222-4567"></row>
  <row ShipperID="3" CompanyName="Federal Shipping" Phone="(503) 333-4567"></row>
</data>

Basically given the input ADO XML - I'm looking to do the following:

  1. Remove all namespace information schema etc but keep the open and close tag (partially done)
  2. <rs:data> needs to become <data> without any attributes (how do I remove that attribute from xmlns from data?)
  3. <rs:insert> needs to disappear (done)
  4. <z:row> needs to become <row> (done)

The input data can vary but will have the same structure - that's the reason I need a generic set of rules as before.

Thank you!

1
Don't pretend to use version="3.0" with MSXML, it is an XSLT 1 processor.Martin Honnen

1 Answers

2
votes

If you need to remove namespaces use

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

and

<xsl:template match="@*">
  <xsl:attribute name="{local-name()}">
    <xsl:value-of select="."/>
  </xsl:attribute>
</xsl:template>

as the base templates.

Then

<xsl:template match="rs:insert">
  <xsl:apply-templates/>
</xsl:template>

For the name changes e.g.

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

Make sure you use e.g. exclude-result-prefixes="z rs" on the xsl:stylesheet element for any namespaces you declare in the XSLT just to select elements or attributes from the input but where you don't want the namespaces to appear in the result.

And don't shoot yourself into the foot by putting the XSLT code into the default namespace so use e.g.

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version = "1.0"
 xmlns:s="uuid:BDC6E3F0-6DA3-11d1-A2A3-00AA00C14882"
 xmlns:rs="urn:schemas-microsoft-com:rowset" xmlns:z="#RowsetSchema" exclude-result-prefixes="z s rs">

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


<xsl:template match="@*">
  <xsl:attribute name="{local-name()}">
    <xsl:value-of select="."/>
  </xsl:attribute>
</xsl:template>


<xsl:template match="rs:insert | xml">
  <xsl:apply-templates/>
</xsl:template>


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

<xsl:template match="s:Schema"/>

</xsl:stylesheet>

https://xsltfiddle.liberty-development.net/jxWZS8g/1