Reputation: 263
I have an issue trying to transform the following. The input has a parent-child relationship which is shown as levels below. The Parent_Identifier
tag helps relate the children to the parent. What is the issue with the XSLT transformation? I've used a transformation which was referred to here in this post: Xslt group parent/child, but I can't seem to get it to work.
<DBAdapterOutputCollection xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.oracle.com/pcbpel/adapter/db/DBAdapter">
<DBAdapterOutput>
<LEVEL>1</LEVEL>
<IDENTIFIER>9536162</IDENTIFIER>
<PARENT_IDENTIFIER xsi:nil="true"/>
<LINE_NUMBER>1.1.0</LINE_NUMBER>
</DBAdapterOutput>
<DBAdapterOutput>
<LEVEL>2</LEVEL>
<IDENTIFIER>9536165</IDENTIFIER>
<PARENT_IDENTIFIER>9536162</PARENT_IDENTIFIER>
<LINE_NUMBER>1.1.1</LINE_NUMBER>
<ORDER_NUMBER>1554828</ORDER_NUMBER>
</DBAdapterOutput>
<DBAdapterOutput>
<LEVEL>2</LEVEL>
<IDENTIFIER>9536173</IDENTIFIER>
<PARENT_IDENTIFIER>9536162</PARENT_IDENTIFIER>
<LINE_NUMBER>1.1.7</LINE_NUMBER>
<ORDER_NUMBER>1554828</ORDER_NUMBER>
</DBAdapterOutput>
<DBAdapterOutput>
<LEVEL>3</LEVEL>
<IDENTIFIER>1227973</IDENTIFIER>
<PARENT_IDENTIFIER>9536165</PARENT_IDENTIFIER>
<LINE_NUMBER>1.1.4</LINE_NUMBER>
<ORDER_NUMBER>1554828</ORDER_NUMBER>
</DBAdapterOutput>
<DBAdapterOutput>
<LEVEL>3</LEVEL>
<IDENTIFIER>1275015</IDENTIFIER>
<PARENT_IDENTIFIER>9536165</PARENT_IDENTIFIER>
<LINE_NUMBER>1.1.4</LINE_NUMBER>
<ORDER_NUMBER>1554828</ORDER_NUMBER>
</DBAdapterOutput>
</DBAdapterOutputCollection>
<WMSAssetInterface_Input xmlns="http://siebel.com/CustomUI">
<ListOfAsset xmlns="http://www.siebel.com/xml/ThinComergentAsset">
<ListOfAssetHeader>
<AssetHeader>
<IntegrationId>9536162 1.1.0</IntegrationId>
<ProductName>1.1.0</ProductName>
<ListOfAssetItem>
<AssetItem>
<IntegrationId>9536162 1.1.0 Level=1</IntegrationId>
<ProductName>1.1.0</ProductName>
<ListOfAssetItem>
<AssetItem>
<IntegrationId>9536165 1.1.1 Level=2</IntegrationId>
<ProductName>1.1.1</ProductName>
<ListOfAssetItem>
<AssetItem>
<IntegrationId>1227973 1.1.4 Level=3</IntegrationId>
<ProductName>1.1.4</ProductName>
</AssetItem>
<AssetItem>
<IntegrationId>1275015 1.1.4 Level=3</IntegrationId>
<ProductName>1.1.4</ProductName>
</AssetItem>
</ListOfAssetItem>
</AssetItem>
<AssetItem>
<IntegrationId>9536173 1.1.7 Level=2</IntegrationId>
<ProductName>1.1.7</ProductName>
</AssetItem>
</ListOfAssetItem>
</AssetItem>
</ListOfAssetItem>
</AssetHeader>
<ListOfAssetHeader>
</ListOfAsset>
</WMSAssetInterface_Input>
<xsl:stylesheet version="1.0" xmlns:ns0="http://xmlns.oracle.com/pcbpel/adapter/db/DBAdapter" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xsdLocal1="http://www.siebel.com/xml/ThinComergentAsset" xmlns:tns="http://siebel.com/CustomUI" exclude-result-prefixes="tns" >
<xsl:template match="/ns0:DBAdapterOutputCollection">
<tns:WMSAssetInterface_Input>
<xsdLocal1:ListOfAsset>
<xsdLocal1:ListOfAssetHeader>
<xsdLocal1:AssetHeader>
<xsdLocal1:IntegrationId>
<xsl:value-of select='concat(ns0:DBAdapterOutput/ns0:IDENTIFIER," ",ns0:DBAdapterOutput/ns0:LINE_NUMBER," Level=",ns0:DBAdapterOutput/ns0:LEVEL)'/>
</xsdLocal1:IntegrationId>
<xsdLocal1:ProductName>
<xsl:value-of select="ns0:DBAdapterOutput/ns0:LINE_NUMBER"/>
</xsdLocal1:ProductName>
<xsl:apply-templates select="ns0:DBAdapterOutputCollection/ns0:DBAdapterOutput[string-length(ns0:PARENT_IDENTIFIER)=0]" />
</xsdLocal1:AssetHeader>
</xsdLocal1:ListOfAssetHeader>
</xsdLocal1:ListOfAsset>
</tns:WMSAssetInterface_Input>
</xsl:template>
<xsl:template match="ns0:DBAdapterOutput">
<xsdLocal1:ListOfAssetItem>
<xsdLocal1:AssetItem>
<xsdLocal1:IntegrationId>
<xsl:value-of select='concat(ns0:IDENTIFIER," ",ns0:LINE_NUMBER," Level=",ns0:LEVEL)'/>
</xsdLocal1:IntegrationId>
<xsdLocal1:PartName>
<xsl:value-of select="ns0:LINE_NUMBER"/>
</xsdLocal1:PartName>
<xsl:variable name="children" select="parent::*/ns0:DBAdapterOutput[ns0:PARENT_IDENTIFIER=current()/ns0:IDENTIFIER]" />
<xsl:if test="$children">
<xsdLocal1:ListOfAssetItem>
<xsdLocal1:AssetItem>
<xsl:apply-templates select="$children" />
</xsdLocal1:AssetItem>
</xsdLocal1:ListOfAssetItem>
</xsl:if>
</xsdLocal1:AssetItem>
</xsdLocal1:ListOfAssetItem>
</xsl:template>
</xsl:stylesheet>
Upvotes: 1
Views: 400
Reputation: 243599
First, an observation about the unreadability of the code -- please in future questions provide well indented code with short lines!
There is one major issue that can be easily corrected.
Change this:
<xsl:apply-templates select=
"ns0:DBAdapterOutputCollection/ns0:DBAdapterOutput
[string-length(ns0:PARENT_IDENTIFIER)=0]" />
to this:
<xsl:apply-templates select=
"ns0:DBAdapterOutput
[string-length(ns0:PARENT_IDENTIFIER)=0]" />
The XSLT instruction that has to be modified is in a template with current node the top
ns0:DBAdapterOutputCollection
element. It specifies that templates should be applied to any of its grand-children ns0:DBAdapterOutput
element that satisfies the condition in the predicate and that is a child of any ns0:DBAdapterOutputCollection
child of the current node.
However, the current node (the top ns0:DBAdapterOutputCollection
element) has no children ns0:DBAdapterOutputCollection
children and the no nodes are selected for execution by this xsl:apply-templates
instruction.
After the above simple code-change is made, the result from the transformation seems like what probably is wanted:
<?xml version="1.0" encoding="utf-8"?>
<tns:WMSAssetInterface_Input xmlns:tns="http://siebel.com/CustomUI" xmlns:ns0="http://xmlns.oracle.com/pcbpel/adapter/db/DBAdapter" xmlns:xsdLocal1="http://www.siebel.com/xml/ThinComergentAsset">
<xsdLocal1:ListOfAsset>
<xsdLocal1:ListOfAssetHeader>
<xsdLocal1:AssetHeader>
<xsdLocal1:IntegrationId>9536162 1.1.0 Level=1</xsdLocal1:IntegrationId>
<xsdLocal1:ProductName>1.1.0</xsdLocal1:ProductName>
<xsdLocal1:ListOfAssetItem>
<xsdLocal1:AssetItem>
<xsdLocal1:IntegrationId>9536162 1.1.0 Level=1</xsdLocal1:IntegrationId>
<xsdLocal1:PartName>1.1.0</xsdLocal1:PartName>
<xsdLocal1:ListOfAssetItem>
<xsdLocal1:AssetItem>
<xsdLocal1:ListOfAssetItem>
<xsdLocal1:AssetItem>
<xsdLocal1:IntegrationId>9536165 1.1.1 Level=2</xsdLocal1:IntegrationId>
<xsdLocal1:PartName>1.1.1</xsdLocal1:PartName>
<xsdLocal1:ListOfAssetItem>
<xsdLocal1:AssetItem>
<xsdLocal1:ListOfAssetItem>
<xsdLocal1:AssetItem>
<xsdLocal1:IntegrationId>1227973 1.1.4 Level=3</xsdLocal1:IntegrationId>
<xsdLocal1:PartName>1.1.4</xsdLocal1:PartName>
</xsdLocal1:AssetItem>
</xsdLocal1:ListOfAssetItem>
<xsdLocal1:ListOfAssetItem>
<xsdLocal1:AssetItem>
<xsdLocal1:IntegrationId>1275015 1.1.4 Level=3</xsdLocal1:IntegrationId>
<xsdLocal1:PartName>1.1.4</xsdLocal1:PartName>
</xsdLocal1:AssetItem>
</xsdLocal1:ListOfAssetItem>
</xsdLocal1:AssetItem>
</xsdLocal1:ListOfAssetItem>
</xsdLocal1:AssetItem>
</xsdLocal1:ListOfAssetItem>
<xsdLocal1:ListOfAssetItem>
<xsdLocal1:AssetItem>
<xsdLocal1:IntegrationId>9536173 1.1.7 Level=2</xsdLocal1:IntegrationId>
<xsdLocal1:PartName>1.1.7</xsdLocal1:PartName>
</xsdLocal1:AssetItem>
</xsdLocal1:ListOfAssetItem>
</xsdLocal1:AssetItem>
</xsdLocal1:ListOfAssetItem>
</xsdLocal1:AssetItem>
</xsdLocal1:ListOfAssetItem>
</xsdLocal1:AssetHeader>
</xsdLocal1:ListOfAssetHeader>
</xsdLocal1:ListOfAsset>
</tns:WMSAssetInterface_Input>
Upvotes: 1
Reputation: 12729
Two compile time errors:
The tns: prefix is not bound to any namespace.
This line from your style-sheet is nonsense.
<xsl:value-of select='concat(/ns0:IDENTIFIER," ",/ns0:LINE_NUMBER," Level=",/ns0:DBAdapterOutput/ns0:LEVEL')'/>
The close tag for your style-sheet is missing.
I fixed a couple of errors in the style-sheet:
The technique here is to use xsl:apply-templates recursively to drill down through the levels. Records are matched up with their parents just by comparing the two link fields, but an alternative method would be to use keys.
This XSLT 1.0 style-sheet...
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ns0="http://xmlns.oracle.com/pcbpel/adapter/db/DBAdapter"
xmlns:xsdLocal1="http://www.siebel.com/xml/ThinComergentAsset"
exclude-result-prefixes="xsl xsdLocal1 ns0">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/">
<WMSAssetInterface_Input xmlns="http://siebel.com/CustomUI">
<ListOfAsset xmlns="http://www.siebel.com/xml/ThinComergentAsset">
<ListOfAssetHeader>
<xsl:apply-templates select="*/ns0:DBAdapterOutput[ns0:LEVEL=1]" />
</ListOfAssetHeader>
</ListOfAsset>
</WMSAssetInterface_Input>
</xsl:template>
<xsl:template match="ns0:DBAdapterOutput[ns0:LEVEL=1]"
xmlns="http://www.siebel.com/xml/ThinComergentAsset">
<AssetHeader>
<IntegrationId>
<xsl:value-of select="concat(ns0:IDENTIFIER,' ',ns0:LINE_NUMBER)" />
</IntegrationId>
<ProductName>
<xsl:value-of select="ns0:LINE_NUMBER" />
</ProductName>
<ListOfAssetItem>
<xsl:apply-templates select="../ns0:DBAdapterOutput
[ ns0:LEVEL=
(current()/ns0:LEVEL+1)]" />
</ListOfAssetItem>
</AssetHeader>
</xsl:template>
<xsl:template match="ns0:DBAdapterOutput[ns0:LEVEL > 1]"
xmlns="http://www.siebel.com/xml/ThinComergentAsset">
<AssetItem>
<IntegrationId>
<xsl:value-of select="concat(ns0:IDENTIFIER,' ',ns0:LINE_NUMBER,
' Level=', ns0:LEVEL/text()-1)" />
</IntegrationId>
<ProductName>
<xsl:value-of select="ns0:LINE_NUMBER" />
</ProductName>
<xsl:if test="../ns0:DBAdapterOutput
[ns0:PARENT_IDENTIFIER = current()/ns0:IDENTIFIER]">
<ListOfAssetItem>
<xsl:apply-templates select="../ns0:DBAdapterOutput
[ns0:PARENT_IDENTIFIER = current()/ns0:IDENTIFIER]" />
</ListOfAssetItem>
</xsl:if>
</AssetItem>
</xsl:template>
</xsl:stylesheet>
...when applied to the sample input, will yield...
<WMSAssetInterface_Input xmlns="http://siebel.com/CustomUI">
<ListOfAsset xmlns="http://www.siebel.com/xml/ThinComergentAsset">
<ListOfAssetHeader>
<AssetHeader>
<IntegrationId>9536162 1.1.0</IntegrationId>
<ProductName>1.1.0</ProductName>
<ListOfAssetItem>
<AssetItem>
<IntegrationId>9536165 1.1.1 Level=1</IntegrationId>
<ProductName>1.1.1</ProductName>
<ListOfAssetItem>
<AssetItem>
<IntegrationId>1227973 1.1.4 Level=2</IntegrationId>
<ProductName>1.1.4</ProductName>
</AssetItem>
<AssetItem>
<IntegrationId>1275015 1.1.4 Level=2</IntegrationId>
<ProductName>1.1.4</ProductName>
</AssetItem>
</ListOfAssetItem>
</AssetItem>
<AssetItem>
<IntegrationId>9536173 1.1.7 Level=1</IntegrationId>
<ProductName>1.1.7</ProductName>
</AssetItem>
</ListOfAssetItem>
</AssetHeader>
</ListOfAssetHeader>
</ListOfAsset>
</WMSAssetInterface_Input>
This is slightly different to your stated expected output, but only because, IMHO, of mistakes in the listed expected output. I believe that this delivers what you want.
Upvotes: 1