Reputation: 485
Whenever I am trying to transform an xml to json, few conditions are not working as expected.
e.g.
XML is
<ns1:OTA_AirSeatMapRS
xmlns:ns1="http://www.opentravel.org/OTA/2003/05"
xmlns="http://www.opentravel.org/OTA/2003/05"
xmlns:fo="http://xml.amadeus.com/SMPRES_97_1_IA"
xmlns:helper="com.openjaw.rules.XSLHelper" Version="1.0" >
<ns1:Success />
<ns1:SeatMapResponses>
<ns1:SeatMapResponse>
<ns1:SeatMapDetails MaxRow="A|C|D|E|F|G|H|K" OverwingEnd="28" OverwingStart="11" SpaceAfter="C|G">
<ns1:CabinClass CabinType="N" EndingRow="44" Name="F" StartingRow="11" cabinLocation="M">
<ns1:AirRows>
<ns1:AirRow MaxNumberOfSeats="6" RowNumber="11">
<ns1:AirSeats>
<ns1:AirSeat SeatAvailability="" SeatCharacteristics="I" SeatNumber="C" />
<ns1:AirSeat SeatAvailability="" SeatCharacteristics="8" SeatNumber="D" />
<ns1:AirSeat SeatAvailability="" SeatCharacteristics="8" SeatNumber="E" />
<ns1:AirSeat SeatAvailability="" SeatCharacteristics="8" SeatNumber="F" />
<ns1:AirSeat SeatAvailability="" SeatCharacteristics="8" SeatNumber="G" />
<ns1:AirSeat SeatAvailability="" SeatCharacteristics="I" SeatNumber="H" />
</ns1:AirSeats>
<ns1:AirRowCharacteristics />
</ns1:AirRow>
<ns1:AirRow MaxNumberOfSeats="1" RowNumber="12">
<ns1:AirSeats>
<ns1:AirSeat SeatAvailability="" SeatCharacteristics="I" SeatNumber="F" />
</ns1:AirSeats>
<ns1:AirRowCharacteristics />
</ns1:AirRow>
<ns1:AirRow MaxNumberOfSeats="0" RowNumber="13">
<ns1:AirSeats />
<ns1:AirRowCharacteristics>Z</ns1:AirRowCharacteristics>
</ns1:AirRow>
<ns1:AirRow MaxNumberOfSeats="0" RowNumber="14">
<ns1:AirSeats />
<ns1:AirRowCharacteristics />
</ns1:AirRow>
<ns1:AirRow MaxNumberOfSeats="3" RowNumber="15">
<ns1:AirSeats>
<ns1:AirSeat SeatAvailability="O" SeatCharacteristics="" SeatNumber="A" />
<ns1:AirSeat SeatAvailability="O" SeatCharacteristics="" SeatNumber="C" />
<ns1:AirSeat SeatAvailability="O" SeatCharacteristics="" SeatNumber="D" />
</ns1:AirSeats>
<ns1:AirRowCharacteristics />
</ns1:AirRow>
</ns1:AirRows>
</ns1:CabinClass>
<
/ns1:SeatMapDetails>
</ns1:SeatMapResponse>
</ns1:SeatMapResponses>
<ns1:cabinLocations>
<ns1:cabinLocation Characteristic="L" Description="Lowerdeck" />
<ns1:cabinLocation Characteristic="M" Description="Maindeck" />
<ns1:cabinLocation Characteristic="U" Description="Upperdeck" />
</ns1:cabinLocations>
</ns1:OTA_AirSeatMapRS>
And XSL is :
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ns1="http://www.opentravel.org/OTA/2003/05"
xmlns:ota="http://www.opentravel.org/OTA/2003/05"
xmlns="http://www.opentravel.org/OTA/2003/05" xmlns:math="http://exslt.org/math"
xmlns:str="http://exslt.org/strings" extension-element-prefixes="str">
<xsl:template match="/">
"seatLayout" : {
<xsl:for-each select="//ns1:cabinLocations/ns1:cabinLocation">
"<xsl:value-of select="@Description"/>" :
{
<xsl:variable name="deck" select="@Characteristic"/>
<xsl:if test="//ns1:CabinClass[@cabinLocation=$deck]">
<xsl:variable name="rowsInDeck" select="//ns1:CabinClass[@cabinLocation=$deck]/../@MaxRow"/>
"equipmentInfo":{
"columns":"<xsl:value-of select="$rowsInDeck"/>",
"columnSpaceAfter":"<xsl:value-of select="//ns1:CabinClass[@cabinLocation=$deck]/../@SpaceAfter"/>",
"wingsStart":"<xsl:value-of select="math:lowest(//ns1:SeatMapDetails[@OverwingStart!='']/ns1:CabinClass[@cabinLocation=$deck]/../@OverwingStart)"/>",
"wingsEnd":"<xsl:value-of select="math:highest(//ns1:SeatMapDetails[@OverwingEnd!='']/ns1:CabinClass[@cabinLocation=$deck]/../@OverwingEnd)"/>",
"cabinName":"<xsl:value-of select="//ns1:CabinClass[@cabinLocation=$deck]/@Name"/>",
"cabinType":"<xsl:value-of select="//ns1:CabinClass[@cabinLocation=$deck]/@CabinType"/>",
"cabinStart":"<xsl:value-of select="math:lowest(//ns1:CabinClass[@cabinLocation=$deck]/@StartingRow)"/>",
"cabinEnd":"<xsl:value-of select="math:highest(//ns1:CabinClass[@cabinLocation=$deck]/@EndingRow)"/>"
}
"rowInfo":{
<xsl:for-each select="//ns1:CabinClass[@cabinLocation=$deck]/ns1:AirRows/ns1:AirRow">
<xsl:variable name="rowNumber" select="@RowNumber"/>
<xsl:variable name="rowCharacteristic" select="//ns1:CabinClass[@cabinLocation=$deck]/ns1:AirRows/ns1:AirRow[@RowNumber=$rowNumber]/ns1:AirRowCharacteristics"/>
"<xsl:value-of select="$rowNumber"/>:{
"rchar":"<xsl:value-of select="$rowCharacteristic" />
"rseats":[
<xsl:for-each select="str:tokenize($rowsInDeck, '|')">
<xsl:variable name="pos" select="position()"/>
<xsl:variable name="seatNumber" select="str:tokenize($rowsInDeck, '|')[position()=$pos]"/>
{
<xsl:value-of select="$deck"/>##<xsl:value-of select="$rowNumber"/>##<xsl:value-of select="$seatNumber"/>
<xsl:if test="boolean(//ns1:CabinClass[@cabinLocation=$deck]/ns1:AirRows/ns1:AirRow[@RowNumber=$rowNumber]/ns1:AirSeats/ns1:AirSeat[@SeatNumber=$seatNumber])">
"available"
</xsl:if>
<xsl:if test="not(boolean(//ns1:CabinClass[@cabinLocation=$deck]/ns1:AirRows/ns1:AirRow[@RowNumber=$rowNumber]/ns1:AirSeats/ns1:AirSeat[@SeatNumber=$seatNumber]))">
"NOT available"
</xsl:if>
}
</xsl:for-each>
]
}
<xsl:if test="position()!=last()">,</xsl:if>
</xsl:for-each>
}
</xsl:if>
}
<xsl:if test="position()!=last()">,</xsl:if>
</xsl:for-each>
}
</xsl:template>
</xsl:stylesheet>
Here if for a sequence of deck->rowNumber->seatNumber is present then it should print available else not available. But the condition is giving false everytime.
Output :
<?xml version="1.0" encoding="UTF-8"?>
"seatLayout" : {
"Lowerdeck" :
{
}
,
"Maindeck" :
{
"equipmentInfo":{
"columns":"A|C|D|E|F|G|H|K",
"columnSpaceAfter":"C|G",
"wingsStart":"11",
"wingsEnd":"28",
"cabinName":"F",
"cabinType":"N",
"cabinStart":"11",
"cabinEnd":"44"
}
"rowInfo":{
"11:{
"rchar":"
"rseats":[
{
M##11##A
"NOT available"
}
{
M##11##C
"NOT available"
}
{
M##11##D
"NOT available"
}
{
M##11##E
"NOT available"
}
{
M##11##F
"NOT available"
}
{
M##11##G
"NOT available"
}
{
M##11##H
"NOT available"
}
{
M##11##K
"NOT available"
}
]
}
,
"12:{
"rchar":"
"rseats":[
{
M##12##A
"NOT available"
}
{
M##12##C
"NOT available"
}
{
M##12##D
"NOT available"
}
{
M##12##E
"NOT available"
}
{
M##12##F
"NOT available"
}
{
M##12##G
"NOT available"
}
{
M##12##H
"NOT available"
}
{
M##12##K
"NOT available"
}
]
}
,
"13:{
"rchar":"Z
"rseats":[
{
M##13##A
"NOT available"
}
{
M##13##C
"NOT available"
}
{
M##13##D
"NOT available"
}
{
M##13##E
"NOT available"
}
{
M##13##F
"NOT available"
}
{
M##13##G
"NOT available"
}
{
M##13##H
"NOT available"
}
{
M##13##K
"NOT available"
}
]
}
,
"14:{
"rchar":"
"rseats":[
{
M##14##A
"NOT available"
}
{
M##14##C
"NOT available"
}
{
M##14##D
"NOT available"
}
{
M##14##E
"NOT available"
}
{
M##14##F
"NOT available"
}
{
M##14##G
"NOT available"
}
{
M##14##H
"NOT available"
}
{
M##14##K
"NOT available"
}
]
}
,
"15:{
"rchar":"
"rseats":[
{
M##15##A
"NOT available"
}
{
M##15##C
"NOT available"
}
{
M##15##D
"NOT available"
}
{
M##15##E
"NOT available"
}
{
M##15##F
"NOT available"
}
{
M##15##G
"NOT available"
}
{
M##15##H
"NOT available"
}
{
M##15##K
"NOT available"
}
]
}
}
}
,
"Upperdeck" :
{
}
}
Please suggest what I am missing here. I am stuck in this for two days.
Upvotes: 1
Views: 1565
Reputation: 70648
To demonstrate the issue, your XSLT can be simplified to this, using some hard-coded values to keep it simple. (Although do note how the declaration of seatNumber
can be simplified to <xsl:variable name="seatNumber" select="." />
rather than re-tokenizing the same string for a second time)
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ns1="http://www.opentravel.org/OTA/2003/05"
xmlns:str="http://exslt.org/strings" extension-element-prefixes="str">
<xsl:output method="text" />
<xsl:template match="/">
<xsl:variable name="deck" select="'M'" />
<xsl:variable name="rowNumber" select="'11'" />
<xsl:variable name="rowsInDeck" select="//ns1:CabinClass[@cabinLocation=$deck]/../@MaxRow"/>
<xsl:for-each select="str:tokenize($rowsInDeck, '|')">
<xsl:variable name="seatNumber" select="." />
<xsl:value-of select="$deck"/>##<xsl:value-of select="$rowNumber"/>##<xsl:value-of select="$seatNumber"/>
<xsl:if test="boolean(//ns1:CabinClass[@cabinLocation=$deck]/ns1:AirRows/ns1:AirRow[@RowNumber=$rowNumber]/ns1:AirSeats/ns1:AirSeat[@SeatNumber=$seatNumber])">
"available"
</xsl:if>
<xsl:if test="not(boolean(//ns1:CabinClass[@cabinLocation=$deck]/ns1:AirRows/ns1:AirRow[@RowNumber=$rowNumber]/ns1:AirSeats/ns1:AirSeat[@SeatNumber=$seatNumber]))">
"NOT available"
</xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
The problem is, your xsl:if
statements that check for availability are within the context of an xsl:for-each
statement which tokenizes the rowsDeck
variable. This means the block of code within xsl:for-each
is in a different context of the original document. You are not iterating over nodes in the source document, but newly created atomic values. This means the expression //ns1:CabinClass
will not work, as your context is not the original XML any more.
I am partially surprised you did not get an error along the following lines:
Leading '/' cannot select the root node of the tree containing the context item: the context item is not a node
Anyway, to solve, you can create a reference to the original document by means of a variable (declared before the xsl:for-each
)
<xsl:variable name="root" select="/" />
Then, you can change your xsl:if
statement to this:
<xsl:if test="boolean($root//ns1:CabinClass[@cabinLocation=$deck]/ns1:AirRows/ns1:AirRow[@RowNumber=$rowNumber]/ns1:AirSeats/ns1:AirSeat[@SeatNumber=$seatNumber])">
Actually, it might be better to use xsl:choose
here, to same specifying the expression twice. It is also unnecessary to use the boolean
operator here. As the expression returns a node, the if
statement will evaluate it to true anyway if it exists, and false if not.
Try this XSLT for starters
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ns1="http://www.opentravel.org/OTA/2003/05"
xmlns:str="http://exslt.org/strings" extension-element-prefixes="str">
<xsl:output method="text" />
<xsl:template match="/">
<xsl:variable name="deck" select="'M'" />
<xsl:variable name="rowNumber" select="'11'" />
<xsl:variable name="rowsInDeck" select="//ns1:CabinClass[@cabinLocation=$deck]/../@MaxRow"/>
<xsl:variable name="root" select="/" />
<xsl:for-each select="str:tokenize($rowsInDeck, '|')">
<xsl:variable name="seatNumber" select="." />
<xsl:value-of select="$deck"/>##<xsl:value-of select="$rowNumber"/>##<xsl:value-of select="$seatNumber"/>
<xsl:choose>
<xsl:when test="$root//ns1:CabinClass[@cabinLocation=$deck]/ns1:AirRows/ns1:AirRow[@RowNumber=$rowNumber]/ns1:AirSeats/ns1:AirSeat[@SeatNumber=$seatNumber]">
"available"
</xsl:when>
<xsl:otherwise>
"NOT available"
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Upvotes: 1