XSLT 1.0 grouping example - xslt-1.0

I have data as my Input XML as below:
<Travelers>
<Surname>GROUPNAME</Surname><PNRNameNumber>1</PNRNameNumber><PassengerNumber>1</PassengerNumber>
<TravelerSegments>
<SegmentNumber>1</SegmentNumber>
<SeatLegRecords>
<SeatBoardPoint>ORD</SeatBoardPoint>
<SeatOffPoint>SFO</SeatOffPoint>
<SeatNumbers>30A</SeatNumbers>
<SeatNumbers>30B</SeatNumbers>
<SeatNumbers>30C</SeatNumbers>
<SeatNumbers>30D</SeatNumbers>
<SeatNumbers>30E</SeatNumbers>
<SeatNumbers>30F</SeatNumbers>
<SeatNumbers>30G</SeatNumbers>
<SeatNumbers>30H</SeatNumbers>
<SeatNumbers>31A</SeatNumbers>
</SeatLegRecords>
<SeatLegRecords>
<SeatBoardPoint>SFO</SeatBoardPoint>
<SeatOffPoint>LAX</SeatOffPoint>
<SeatNumbers>30A</SeatNumbers>
<SeatNumbers>30B</SeatNumbers>
<SeatNumbers>30C</SeatNumbers>
<SeatNumbers>30D</SeatNumbers>
<SeatNumbers>30E</SeatNumbers>
<SeatNumbers>30F</SeatNumbers>
<SeatNumbers>30G</SeatNumbers>
<SeatNumbers>30H</SeatNumbers>
<SeatNumbers>31A</SeatNumbers>
</SeatLegRecords>
</TravelerSegments>
And I want my output to display such as -
{
[ "30A","30B",30C","30D","30E","30F","30G","30H","31A"],
[ "30A","30B",30C","30D","30E","30F","30G","30H","31A"]
}
Can some one help me with XSLT 1.0 ? I know it is easy in XSLT 2.0 . But, i do not have XLST 2.0 available in my environment.

Try this.
<xsl:template match="TravelerSegments">
<xsl:value-of select="'{
'"/>
<xsl:apply-templates select=".//SeatLegRecords"/>
<xsl:value-of select="'
}'"/>
</xsl:template>
<xsl:template match="SeatLegRecords">
<xsl:if test="position() > 1">
<xsl:value-of select="',
'"/>
</xsl:if>
<xsl:value-of select="'['"/>
<xsl:apply-templates select=".//SeatNumbers"/>
<xsl:value-of select="']'"/>
</xsl:template>
<xsl:template match="SeatNumbers">
<xsl:if test="position() > 1">
<xsl:value-of select="','"/>
</xsl:if>
<xsl:value-of select="concat('"',.,'"')"/>
</xsl:template>
<xsl:template match="node()">
<xsl:apply-templates select="node()"/>
</xsl:template>

Related

Otherwise XSLT1.0 - correct output

I´ve a problem at my xslt.
Here it is:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="GRP">
<xsl:copy>
<!--copy the data from ADD - ST to the GRP so it can be used in the mapping to set the delivery address from end customer-->
<xsl:for-each select ="./ADD">
<xsl:if test="./QUALIFIER='ST'">
<xsl:copy-of select="PARTY_NAME_1"/>
<xsl:copy-of select="STREET_1"/>
<xsl:copy-of select="CITY"/>
<xsl:copy-of select="POSTAL_CODE"/>
<xsl:copy-of select="COUNTRY_CODE"/>
</xsl:if>
<xsl:choose>
<xsl:when test="./QUALIFIER='CN'">
<CONTACT_NUMBER>
<xsl:value-of select="CONTACT/NUMBER"/>
</CONTACT_NUMBER>
</xsl:when>
<xsl:otherwise>
<xsl:if test="./QUALIFIER='ST'">
<CONTACT_NUMBER>
<xsl:value-of select="CONTACT/NUMBER"/>
</CONTACT_NUMBER>
</xsl:if>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
<!--copy all other nodes-->
<xsl:apply-templates select="#* | node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Can you tell me, whats my mistake at my xml?
At my code i get Contact_Number 2 times.
I just like one of them... If Contact at CN - use this, otherwise use from ST.
-> If contact at CN and ST use CN.
Edit: xml:
<SEEDELFOR>
<GRP>
<ADD>
<QUALIFIER>CN</QUALIFIER>
<IDENTIFIER></IDENTIFIER>
<AGENCY_CODE></AGENCY_CODE>
<PARTY_NAME_1></PARTY_NAME_1>
<STREET_1></STREET_1>
<CITY></CITY>
<POSTAL_CODE></POSTAL_CODE>
<COUNTRY_CODE></COUNTRY_CODE>
<CONTACT>
<QUALIFIER></QUALIFIER>
<NUMBER>1111111</NUMBER>
</CONTACT>
</ADD>
<ADD>
<QUALIFIER>ST</QUALIFIER>
<IDENTIFIER></IDENTIFIER>
<AGENCY_CODE></AGENCY_CODE>
<PARTY_NAME_1></PARTY_NAME_1>
<STREET_1></STREET_1>
<CITY></CITY>
<POSTAL_CODE></POSTAL_CODE>
<CONTACT>
<QUALIFIER></QUALIFIER>
<NUMBER>2222222</NUMBER>
</CONTACT>
</ADD>
</GRP>
</SEEDELFOR>
How can i correct my xslt?
I hope you can help me.
Best regards
Julian
One of the way you can achieve this is, rewriting the template GRP as following:
<xsl:template match="GRP">
<xsl:copy>
<!--copy the data from ADD - ST to the GRP so it can be used in the mapping
to set the delivery address from end customer -->
<xsl:variable name="contact_ST">
<xsl:for-each select="./ADD">
<xsl:if test="./QUALIFIER='ST'">
<CONTACT_NUMBER>
<xsl:value-of select="CONTACT/NUMBER" />
</CONTACT_NUMBER>
</xsl:if>
</xsl:for-each>
</xsl:variable>
<xsl:variable name="contact_CN">
<xsl:for-each select="./ADD">
<xsl:if test="./QUALIFIER='CN'">
<CONTACT_NUMBER>
<xsl:value-of select="CONTACT/NUMBER" />
</CONTACT_NUMBER>
</xsl:if>
</xsl:for-each>
</xsl:variable>
<xsl:for-each select="./ADD">
<xsl:if test="./QUALIFIER='ST'">
<xsl:copy-of select="PARTY_NAME_1" />
<xsl:copy-of select="STREET_1" />
<xsl:copy-of select="CITY" />
<xsl:copy-of select="POSTAL_CODE" />
<xsl:copy-of select="COUNTRY_CODE" />
</xsl:if>
</xsl:for-each>
<xsl:choose>
<xsl:when test="$contact_CN != ''">
<xsl:copy-of select="$contact_CN" />
</xsl:when>
<xsl:otherwise>
<xsl:copy-of select="$contact_ST" />
</xsl:otherwise>
</xsl:choose>
<!--copy all other nodes -->
<xsl:apply-templates select="#* | node()" />
</xsl:copy>
</xsl:template>
Consider the following simplified example:
<xsl:template match="GRP">
<xsl:copy>
<!-- other code, if necessary-->
<xsl:variable name="cn" select="ADD[QUALIFIER='CN']" />
<xsl:variable name="st" select="ADD[QUALIFIER='ST']" />
<CONTACT_NUMBER>
<xsl:choose>
<xsl:when test="$cn">
<xsl:value-of select="$cn/CONTACT/NUMBER"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$st/CONTACT/NUMBER"/>
</xsl:otherwise>
</xsl:choose>
</CONTACT_NUMBER>
<!-- more code, if necessary-->
</xsl:copy>
</xsl:template>

How to make element with <xsl:attribute> when using <sql:query>

I am using saxonee-sql to connect to a database. How do I make the output xml file like this:
<Partners>
<Partner type="Supplier">
<PartnerName>name 1</PartnerName>
<PartnerDuns>duns 1</PartnerDuns>
</Partner>
<Partner type="Buyer">
<PartnerName>name 2</PartnerName>
<PartnerDuns>dums 2</PartnerDuns>
</Partner>
</Partners>
And this is the xslt:
<xsl:variable name="partner">
<sql:query connection="$connection" table="Partner" column="PartnerDuns,PartnerName,type" row-tag="Partner" />
</xsl:variable>
<Partners>
<xsl:copy-of select="$partner" />
</Partners>
The current output is
<Partners>
<Partner>
<PartnerName>name 1</PartnerName>
<PartnerDuns>duns 1</PartnerDuns>
<type>Supplier</type>
</Partner>
<Partner>
<PartnerName>name 2</PartnerName>
<PartnerDuns>dums 2</PartnerDuns>
<type>Buyer</type>
</Partner>
</Partners>
I suppose you can simply transform the original result with e.g.
<xsl:template match="Partner/*">
<xsl:copy-of select="."/>
</xsl:template>
<xsl:template match="Partner/type">
<xsl:attribute name="{name()}" select="."/>
</xsl:template>
<xsl:template match="Partner">
<xsl:copy>
<xsl:apply-templates select="type, (* except type)"/>
</xsl:copy>
</xsl:template>
and then use
<xsl:variable name="partner">
<sql:query connection="$connection" table="Partner" column="PartnerDuns,PartnerName,type" row-tag="Partner" />
</xsl:variable>
<Partners>
<xsl:apply-templates select="$partner/*" />
</Partners>
instead of the copy-of.

Reading values of XML tag in variables inside XSLT

I could not find a similar question anywhere, so thats why posting this new question.
I have an XML that I want to read and convert into SQL using XSLT. The trick part is that the XML elements(i.e. the names) are not known and the XSD for the XML is generated on the fly.
But what is known is certain attributes of the elements.
The XML looks like this :
<?xml version="1.0" encoding="UTF-8"?>
<et:ItemRecordList xmlns:et="urn:org:easetech:easytest:schema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:org:easetech:easytest:schema ItemRecord.xsd ">
<ItemRecord recordId="idvalue0" tableName="item_record">
<itemId columnName="item_id" idColumn="true" length="36" nullable="false">itemId</itemId>
<databaseInstitution columnName="database_institution" length="255" nullable="false">0</databaseInstitution>
<lastModifiedDate columnName="last_modified_date" length="255" nullable="false">2001-12-31T12:00:00</lastModifiedDate>
</ItemRecord>
</et:ItemRecordList>
I want to use this XML and convert it into an INSERT SQL statement using XXSLT.
I created an XSLT like this :
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" encoding="UTF-8" />
<xsl:template match="/">
<xsl:for-each select="/*/*">
INSERT INTO
<xsl:value-of select="#tableName" />
(
<xsl:for-each select="/*/*/*">
<xsl:variable name="columnName"><xsl:value-of select="#columnName"/></xsl:variable>
<xsl:choose>
<xsl:when test="#columnName">
<xsl:value-of select="$columnName"/>
<xsl:if test="position()!=last()">
<xsl:text>, </xsl:text>
</xsl:if>
</xsl:when>
</xsl:choose>
</xsl:for-each>
)
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
which gives me the output like this :
INSERT INTO item_record (item_id, database_institution, last_modified_date)
But I don't know how to create the value part of the query. The value is the value we get using
<xsl:value-of select="." />
I tried concatenating the values, but unfortunately concat didnt work for me. I also played around with xsl:variable but couldnt make it work. If someone could help me with the XSLT that I can use to create to output like below that would be really appreciated.
INSERT INTO item_record (item_id, database_institution, last_modified_date) values (itemId,0,2001-12-31T12:00:00)
How about:
<xsl:template match="/">
<xsl:for-each select="/*/*">
<xsl:text>INSERT INTO </xsl:text>
<xsl:value-of select="#tableName" />
<xsl:text> (</xsl:text>
<xsl:for-each select="*[#columnName]">
<xsl:value-of select="#columnName"/>
<xsl:if test="position()!=last()">
<xsl:text>, </xsl:text>
</xsl:if>
</xsl:for-each>
<xsl:text>) values (</xsl:text>
<xsl:for-each select="*[#columnName]">
<xsl:value-of select="."/>
<xsl:if test="position()!=last()">
<xsl:text>, </xsl:text>
</xsl:if>
</xsl:for-each>
</xsl:for-each>
</xsl:template>
The next XSLT will generate the query as wanted
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" />
<xsl:variable name="newline" select="'
'" />
<xsl:template match="/">
<xsl:apply-templates select="*/*/#tableName" />
</xsl:template>
<xsl:template match="#tableName">
<xsl:value-of select="concat('INSERT INTO ', ., ' (')" />
<xsl:apply-templates select="parent::*/*/#columnName" />
<xsl:value-of select="') VALUES ('" />
<xsl:apply-templates select="parent::*/*" mode="values" />
<xsl:value-of select="concat(')', $newline)" />
</xsl:template>
<xsl:template match="#columnName">
<xsl:choose>
<xsl:when test="position() = last()">
<xsl:value-of select="." />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="concat(., ', ')" />
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="*" mode="values">
<xsl:choose>
<xsl:when test="position() = last()">
<xsl:value-of select="." />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="concat(., ', ')" />
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>

How do I swap ani and dnis values around if direction is 0? If direction is 1 it should be left unchanged

How do I swap ani and dnis values around if direction is 0? If direction is 1 it should be left unchanged.
I have tried with a if command but can get it to work. I hope samebody have a solution for this little issue :)
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes" />
<xsl:template match="/">
<Call xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Data>
<time_offset>
<xsl:number value="0"/>
</time_offset>
<audio>
<audio_segement>
<channel_id>0</channel_id>
<recording_order>1</recording_order>
<audio_url>
<xsl:value-of select="callinfo/location"/>
</audio_url>
<xsl:apply-templates select="callinfo/startdate"/>
<xsl:apply-templates select="StartTime"/>
<Duration>
<xsl:value-of select="callinfo/duration"/>
</Duration>
</audio_segement>
</audio>
<direction>
<xsl:value-of select="callinfo/direction"/>
</direction>
<ani>
<xsl:value-of select="callinfo/local"/>
</ani>
<dnis>
<xsl:value-of select="callinfo/remote"/>
</dnis>
<unique_identifier>
<xsl:value-of select="callinfo/startdate"/>
</unique_identifier>
<pbx_login_id>
<xsl:value-of select="callinfo/local"/>
</pbx_login_id>
<switch_name>Mobile Data Source</switch_name>
</Data>
</Call>
</xsl:template>
<xsl:template match="callinfo/startdate">
<StartTime>
<xsl:variable name="StartTime">
<xsl:value-of select="concat(substring-before(., ' '), 'T', substring-after(., ' '))"/>
</xsl:variable>
<xsl:variable name="startTimeSize" select = "string-length(.)"/>
<xsl:if test="$startTimeSize = 19">
<xsl:value-of select="$StartTime"/>.00+00:00
</xsl:if>
<xsl:if test="$startTimeSize = 33">
<xsl:value-of select="substring($StartTime,0,24)"/>
<xsl:value-of select="substring($StartTime,28,7)"/>
</xsl:if>
<xsl:if test="$startTimeSize != 33 and $startTimeSize != 19">
<xsl:value-of select="$StartTime"/>
</xsl:if>
</StartTime>
</xsl:template>
</xsl:stylesheet>
Any help will be greatly appreciated.
I am still not sure I understand this. If you just want to change the order in which the elements appear in the output document, without changing their contents, change this part:
<ani>
<xsl:value-of select="callinfo/local"/>
</ani>
<dnis>
<xsl:value-of select="callinfo/remote"/>
</dnis>
to:
<xsl:choose>
<xsl:when test="callinfo/direction=1">
<ani><xsl:value-of select="callinfo/local"/></ani>
<dnis><xsl:value-of select="callinfo/remote"/></dnis>
</xsl:when>
<xsl:otherwise>
<dnis><xsl:value-of select="callinfo/remote"/></dnis>
<ani><xsl:value-of select="callinfo/local"/></ani>
</xsl:otherwise>
</xsl:choose>
Note that in a well-designed XML, the order of siblings should not matter - that's what element names are there for.

Looking to insert div into html body with xsl 1.0

Pretty simple: What I'm looking for a simple XSL to change
<body>
...
</body>
To
<body>
...
<div>...</div>
</body>
<xsl:template match="body">
<xsl:apply-templates />
<div>...</div>
</xsl:template>
<xsl:template match="*">
<xsl:variable name="curTagName" select="name()"/>
<xsl:element name="{$curTagName}">
<!-- Walk through the attributes -->
<xsl:apply-templates select="#*">
<xsl:sort select="name()"/>
</xsl:apply-templates>
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
<xsl:template match="#*">
<xsl:variable name="curAttName" select="name()"/>
<xsl:attribute name="{$curAttName}">
<xsl:value-of select="."/>
</xsl:attribute>
</xsl:template>