I am trying to transform an XML output from our accounting system into an XML that can be imported into Access. Unfortunately Access only accepts XSL 1.0 for transformation, so I have asked already for help in transforming a XSL 2.0 solution into something that works under XSL 1.0. (Grouping problem). The solution there worked perfectly for what I thought I needed for the Access import.
The Access import works now but I realize the data is in a form that is still not really usable. The data consists of header rows and sub-rows, which are not filled with the header data. But to aggregate meaningfully, the data would need to be filled.
This is how the current XML imported into Access looks like:
DBCDATE |DBBCPARTY |DBCVCHTYPE |DBCVCHNO |DBCVCHREF
1-Apr-2011 | |Stock Journal |1 |
|ME KN YARN B | | |
|ME KN YARN G | | |
|ME KN YARN I | | |
3-Apr-2011 | |Stock Journal |2 |903
|TIB Raw Wool | | |
|ME KN YARN D | | |
The fields from the header row would need to be copied down also into the sub-rows: DBCDATE, DBCVCHTYPE, DBCVCHNO, DBCVCHREF, DBCNARR.
I could do this with some VBA programming in Access or even export the data into Excel and apply some formulas, but the data is quite large and we are looking into extracting even more. And it would be less flexible. Also, the question probably goes into the direction of grouping an already grouped XML even more (now it is grouped into importable rows in form of the InventoryDaybook tag structure.
So this was the original XML: Edit: Enhanced XML fragment for better testing
<ENVELOPE>
<DBCFIXED> <DBCDATE>1-Apr-2011</DBCDATE>
<DBCPARTY></DBCPARTY>
</DBCFIXED>
<DBCVCHTYPE>Stock Journal</DBCVCHTYPE>
<DBCVCHNO>1</DBCVCHNO>
<DBCVCHREF></DBCVCHREF>
<DBCSTNO></DBCSTNO>
<DBCSERVICETAXNO></DBCSERVICETAXNO>
<DBCPANNO></DBCPANNO>
<DBCCSTNO></DBCCSTNO>
<DBCNARR>Opening balance transfar</DBCNARR>
<DBCQTY>0.000 Kg</DBCQTY>
<DBCRATE></DBCRATE>
<DBCAMOUNT></DBCAMOUNT>
<DBCADDLCOST></DBCADDLCOST>
<DBCGROSSAMT></DBCGROSSAMT>
<DBCLEDAMT></DBCLEDAMT>
<DBCFIXED> <DBCDATE></DBCDATE>
<DBCPARTY>ME KN YARN BL 1</DBCPARTY>
</DBCFIXED>
<DBCVCHTYPE></DBCVCHTYPE>
<DBCVCHNO></DBCVCHNO>
<DBCVCHREF></DBCVCHREF>
<DBCSTNO></DBCSTNO>
<DBCSERVICETAXNO></DBCSERVICETAXNO>
<DBCPANNO></DBCPANNO>
<DBCCSTNO></DBCCSTNO>
<DBCNARR></DBCNARR>
<DBCQTY>0.150 Kg</DBCQTY>
<DBCRATE>566.00/Kg</DBCRATE>
<DBCAMOUNT>-84.90</DBCAMOUNT>
<DBCADDLCOST></DBCADDLCOST>
<DBCGROSSAMT></DBCGROSSAMT>
<DBCLEDAMT></DBCLEDAMT>
<DBCFIXED> <DBCDATE>1-Apr-2011</DBCDATE>
<DBCPARTY></DBCPARTY>
</DBCFIXED>
<DBCVCHTYPE>Stock Journal</DBCVCHTYPE>
<DBCVCHNO>2</DBCVCHNO>
<DBCVCHREF>903</DBCVCHREF>
<DBCSTNO></DBCSTNO>
<DBCSERVICETAXNO></DBCSERVICETAXNO>
<DBCPANNO></DBCPANNO>
<DBCCSTNO></DBCCSTNO>
<DBCNARR>Opening balance transfar</DBCNARR>
<DBCQTY>0.000 Kg</DBCQTY>
<DBCRATE></DBCRATE>
<DBCAMOUNT></DBCAMOUNT>
<DBCADDLCOST></DBCADDLCOST>
<DBCGROSSAMT></DBCGROSSAMT>
<DBCLEDAMT></DBCLEDAMT>
<DBCFIXED> <DBCDATE></DBCDATE>
<DBCPARTY>ME KN YARN BL 1</DBCPARTY>
</DBCFIXED>
<DBCVCHTYPE></DBCVCHTYPE>
<DBCVCHNO></DBCVCHNO>
<DBCVCHREF></DBCVCHREF>
<DBCSTNO></DBCSTNO>
<DBCSERVICETAXNO></DBCSERVICETAXNO>
<DBCPANNO></DBCPANNO>
<DBCCSTNO></DBCCSTNO>
<DBCNARR></DBCNARR>
<DBCQTY>0.260 Kg</DBCQTY>
<DBCRATE>26.00/Kg</DBCRATE>
<DBCAMOUNT>-8.70</DBCAMOUNT>
<DBCADDLCOST></DBCADDLCOST>
<DBCGROSSAMT></DBCGROSSAMT>
<DBCLEDAMT></DBCLEDAMT>
<DBCFIXED> <DBCDATE></DBCDATE>
<DBCPARTY>ME KN YARN BL 1</DBCPARTY>
</DBCFIXED>
<DBCVCHTYPE></DBCVCHTYPE>
<DBCVCHNO></DBCVCHNO>
<DBCVCHREF></DBCVCHREF>
<DBCSTNO></DBCSTNO>
<DBCSERVICETAXNO></DBCSERVICETAXNO>
<DBCPANNO></DBCPANNO>
<DBCCSTNO></DBCCSTNO>
<DBCNARR></DBCNARR>
<DBCQTY>0.360 Kg</DBCQTY>
<DBCRATE>21.00/Kg</DBCRATE>
<DBCAMOUNT>-45.80</DBCAMOUNT>
<DBCADDLCOST></DBCADDLCOST>
<DBCGROSSAMT></DBCGROSSAMT>
<DBCLEDAMT></DBCLEDAMT>
</ENVELOPE>
This is the XSL (XSLT 1.0), slightly changed from the solution:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" omit-xml-declaration="yes" indent="yes"/>
<xsl:key name="records" match="ENVELOPE/*[not(self::DBCFIXED)]" use="generate-id(preceding-sibling::DBCFIXED[1])" />
<xsl:template match="/ENVELOPE">
<Data>
<xsl:apply-templates select="DBCFIXED" />
</Data>
</xsl:template>
<xsl:template match="DBCFIXED">
<InventoryDaybook>
<xsl:copy-of select="./*" />
<xsl:apply-templates select="key('records', generate-id())" />
</InventoryDaybook>
</xsl:template>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Edit: Provided resulting XML (Thank you Martin for pointing out the missing resulting XML)
This is how the XML in the end should look like: The InventoryDaybook wrapping tags have been further distinguished into a 'header' tag containing information on the Date, the Voucher Type, the Voucher Number, the Voucher Reference and the Narration. These fields DBCDATE, DBCVCHTYPE, DBCVCHNO, DBCVCHREF, DBCNARR would need to be copied to the other InventoryDaybook wrapping tags, which represent 'sub' rows. 'Headers' can be identified by DBCDATE - this field is only set for header rows.
<Data>
<InventoryDaybook name="header">
<DBCDATE>1-Apr-2011</DBCDATE>
<DBCPARTY/>
<DBCVCHTYPE>Stock Journal</DBCVCHTYPE>
<DBCVCHNO>1</DBCVCHNO>
<DBCVCHREF/>
<DBCSTNO/>
<DBCSERVICETAXNO/>
<DBCPANNO/>
<DBCCSTNO/>
<DBCNARR>Opening balance transfar</DBCNARR>
<DBCQTY>0.000 Kg</DBCQTY>
<DBCRATE/>
<DBCAMOUNT/>
<DBCADDLCOST/>
<DBCGROSSAMT/>
<DBCLEDAMT/>
</InventoryDaybook>
<InventoryDaybook name="sub">
<DBCDATE>1-Apr-2011</DBCDATE>
<DBCPARTY>ME KN YARN BL 1</DBCPARTY>
<DBCVCHTYPE>Stock Journal</DBCVCHTYPE>
<DBCVCHNO>1</DBCVCHNO>
<DBCVCHREF/>
<DBCSTNO/>
<DBCSERVICETAXNO/>
<DBCPANNO/>
<DBCCSTNO/>
<DBCNARR>Opening balance transfar</DBCNARR>
<DBCQTY>0.150 Kg</DBCQTY>
<DBCRATE>566.00/Kg</DBCRATE>
<DBCAMOUNT>-84.90</DBCAMOUNT>
<DBCADDLCOST/>
<DBCGROSSAMT/>
<DBCLEDAMT/>
</InventoryDaybook>
<InventoryDaybook name="header">
<DBCDATE>1-Apr-2011</DBCDATE>
<DBCPARTY/>
<DBCVCHTYPE>Stock Journal</DBCVCHTYPE>
<DBCVCHNO>2</DBCVCHNO>
<DBCVCHREF>903</DBCVCHREF>
<DBCSTNO/>
<DBCSERVICETAXNO/>
<DBCPANNO/>
<DBCCSTNO/>
<DBCNARR>Opening balance transfar</DBCNARR>
<DBCQTY>0.000 Kg</DBCQTY>
<DBCRATE/>
<DBCAMOUNT/>
<DBCADDLCOST/>
<DBCGROSSAMT/>
<DBCLEDAMT/>
</InventoryDaybook>
<InventoryDaybook name="sub">
<DBCDATE>1-Apr-2011</DBCDATE>
<DBCPARTY>ME KN YARN BL 1</DBCPARTY>
<DBCVCHTYPE>Stock Journal</DBCVCHTYPE>
<DBCVCHNO>2</DBCVCHNO>
<DBCVCHREF>903</DBCVCHREF>
<DBCSTNO/>
<DBCSERVICETAXNO/>
<DBCPANNO/>
<DBCCSTNO/>
<DBCNARR>Opening balance transfar</DBCNARR>
<DBCQTY>0.260 Kg</DBCQTY>
<DBCRATE>26.00/Kg</DBCRATE>
<DBCAMOUNT>-8.70</DBCAMOUNT>
<DBCADDLCOST/>
<DBCGROSSAMT/>
<DBCLEDAMT/>
</InventoryDaybook>
<InventoryDaybook name="sub">
<DBCDATE>1-Apr-2011</DBCDATE>
<DBCPARTY>ME KN YARN BL 1</DBCPARTY>
<DBCVCHTYPE>Stock Journal</DBCVCHTYPE>
<DBCVCHNO>2</DBCVCHNO>
<DBCVCHREF>903</DBCVCHREF>
<DBCSTNO/>
<DBCSERVICETAXNO/>
<DBCPANNO/>
<DBCCSTNO/>
<DBCNARR>Opening balance transfar</DBCNARR>
<DBCQTY>0.360 Kg</DBCQTY>
<DBCRATE>21.00/Kg</DBCRATE>
<DBCAMOUNT>-45.80</DBCAMOUNT>
<DBCADDLCOST/>
<DBCGROSSAMT/>
<DBCLEDAMT/>
</InventoryDaybook>
</Data>
Is there a way to do this in XSL? Also I was wondering if this means to kind of transform the returned XML again? Something like in this solution? Solution to double transformation question
I realize that I am asking twice on the forum for the same larger problem but I am really grateful for your help on this.