I have this source xml
<?xml version="1.0" encoding="UTF-8" ?>
<Document xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<StartOfTransmission>
<SenderId>SENDERSID</SenderId>
<ReceiverId>RECEIVERSID</ReceiverId>
<TRANSDATE>13-09-2010</TRANSDATE>
<TRANSTIME>12:00:00</TRANSTIME>
<SenderReference>1234</SenderReference>
<ReceiverReference/>
<ApplicationReference>ORDHDR</ApplicationReference>
</StartOfTransmission>
</Document>
and I would like to convert it to this format using a stylesheet transformation. (please note the a: and xmlns: prefixes are required.)
<?xml version="1.0" encoding="UTF-8"?>
<a:Document xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://127.0.0.1:8080 http://127.0.0.1:8080/test/tbattributesxml2.xsd"
xmlns:a="http://127.0.0.1:8080">
<a:StartOfTransmission SenderId="SENDERSID" ReceiverId="RECEIVERSID" transdatetime="2010-09-13T12:00:00.000" SenderReference="1234" ReceiverReference="" ApplicationReference="ORDHDR"/>
</a:Document>
Once it is converted correctly the target xml will pass this xsd validation below.
<xs:schema attributeFormDefault="unqualified"
elementFormDefault="qualified"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://127.0.0.1:8080"
xmlns:vc="http://www.w3.org/2007/XMLSchema-versioning"
xmlns:w="http://127.0.0.1:8080"
vc:minVersion="1.1" >
<xs:element name="Document">
<xs:complexType>
<xs:sequence>
<xs:element ref="w:StartOfTransmission" minOccurs="1" maxOccurs="1"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="StartOfTransmission">
<xs:complexType>
<xs:attribute name="SenderId" use="required">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:minLength value="1"/>
<xs:maxLength value="14"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="ReceiverId" use="required">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:minLength value="1"/>
<xs:maxLength value="14"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="transdatetime" use="required" type="xs:dateTime"/>
<xs:attribute name="SenderReference" use="required">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:minLength value="1"/>
<xs:maxLength value="14"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="ReceiverReference" use="optional">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:minLength value="0"/>
<xs:maxLength value="14"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="ApplicationReference" use="required">
<xs:annotation>
<xs:documentation>Value = ORDHDR</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="ORDHDR"/>
<xs:minLength value="1"/>
<xs:maxLength value="14"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:schema>
I have started this stylesheet below which half works (except the colons are missing). When i try to introduce the a: and xmlns: tags it breaks. And I can't get the 'xmlns:xsd="http://www.w3.org/2001/XMLSchema"' to appear as the first attribute in the Document element. As always, any help gratefully received.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:saxon="http://saxon.sf.net/"
xmlns:a="http://127.0.0.1:8080"
exclude-result-prefixes="xs"
version="2.0" >
<xsl:output method="xml" indent="no" />
<xsl:strip-space elements="*"/>
<xsl:template match="/">
<xsl:text>
</xsl:text>
<xsl:apply-templates mode="copy" select="."/>
</xsl:template>
<xsl:template match="*|text()" mode="copy">
<xsl:copy>
<xsl:apply-templates mode="copy"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Document" mode="copy" name="a" >
<xsl:copy>
<xsl:attribute name="{'xmlnsxsd'}"><xsl:value-of select="'http://www.w3.org/2001/XMLSchema'"/></xsl:attribute>
<xsl:attribute name="{'xsi:schemaLocation'}"><xsl:value-of select="'http://127.0.0.1:8080 http://127.0.0.1:8080/tbattributesxml2.xsd'"/></xsl:attribute>
<xsl:attribute name="{'xmlnsa'}"><xsl:value-of select="'http://127.0.0.1:8080'"/></xsl:attribute>
<xsl:apply-templates mode="copy"/>
</xsl:copy>
</xsl:template>
<xsl:template match="StartOfTransmission" mode="copy">
<xsl:text>
	</xsl:text>
<xsl:copy>
<xsl:apply-templates mode="convert-to-attr" select="SenderId"/>
<xsl:apply-templates mode="convert-to-attr" select="ReceiverId"/>
<xsl:variable name="dte" as="xs:string">
<xsl:value-of select="concat(substring(TRANSDATE, 7, 4), '-', substring(TRANSDATE, 4, 2), '-', substring(TRANSDATE, 1, 2))"/>
</xsl:variable>
<xsl:variable name="tme" as="xs:string" select="TRANSTIME"/>
<xsl:variable name="dateTime" select="concat($dte,'T',$tme,'.000')"/>
<xsl:attribute name="transdatetime"><xsl:value-of select="$dateTime"/></xsl:attribute>
<xsl:apply-templates mode="convert-to-attr" select="SenderReference"/>
<xsl:apply-templates mode="convert-to-attr" select="ReceiverReference"/>
<xsl:apply-templates mode="convert-to-attr" select="ApplicationReference"/>
</xsl:copy>
<xsl:text>
</xsl:text>
</xsl:template>
<xsl:template match="*" mode="convert-to-attr">
<xsl:attribute name="{name()}" select="text()"/>
</xsl:template>
</xsl:stylesheet>
CodePudding user response:
AFAICT, all you need to do is:
XSLT 2.0
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:a="http://127.0.0.1:8080">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/Document">
<a:Document xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://127.0.0.1:8080 http://127.0.0.1:8080/test/tbattributesxml2.xsd">
<xsl:apply-templates/>
</a:Document>
</xsl:template>
<xsl:template match="StartOfTransmission">
<a:StartOfTransmission transdatetime="{replace(TRANSDATE, '(.{2})-(.{2})-(.{4})', '$3-$2-$1')}T{TRANSTIME}">
<xsl:apply-templates select="* except(TRANSDATE, TRANSTIME)"/>
</a:StartOfTransmission>
</xsl:template>
<xsl:template match="StartOfTransmission/*">
<xsl:attribute name="{name()}" select="."/>
</xsl:template>
</xsl:stylesheet>
Note that this assumes TRANSDATE
is in DD-MM-YYYY
format (i.e. has a leading zero for day where needed).