Looking to insert div into html body with xsl 1.0 - xslt-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>

Related

Getting a template to apply a class to a span based on conditional results of passed in parameters

This is only a test script and I can supply a two test XML data blocks if required.
The script:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msa="http://www.publictalksoftware.co.uk/msa">
<xsl:output method="html" indent="yes" version="4.01"
doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
doctype-public="//W3C//DTD XHTML 1.0 Transitional//EN"/>
<xsl:variable name="PubDB" select="document('MSA_PublisherDatabase.XML')"/>
<xsl:template match="/">
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title>Test</title>
</head>
<body>
<xsl:for-each select="MeetingWorkBook/Meeting">
<xsl:call-template name="IsAvailableMidweek">
<xsl:with-param name="strName" select="Chairman"/>
</xsl:call-template>
</xsl:for-each>
</body>
</html>
</xsl:template>
<xsl:template name="IsAvailableMidweek">
<xsl:param name="strName"/>
<xsl:variable name="thePublisher" select="$PubDB/msa:PublisherDatabase/msa:Publishers/msa:Publisher[msa:Name=$strName]"/>
<xsl:if test="$thePublisher">
<xsl:choose>
<xsl:when test="$thePublisher/msa:Availability/#Midweek='false'">
<p>Not available #Midweek</p>
</xsl:when>
<xsl:otherwise>
<xsl:variable name ="datMonth" select="format-number(MeetingDate/#Month,'00')"/>
<xsl:variable name ="datDay" select="format-number(MeetingDate/#Day,'00')"/>
<xsl:variable name="datMeeting" select="concat(MeetingDate/#Year, '-', $datMonth, '-', $datDay)"/>
<xsl:choose>
<xsl:when test="$thePublisher/msa:Availability/msa:DatesNotAvailable[msa:Date=$datMeeting]">
<p>
<xsl:text>Not available for date </xsl:text>
<xsl:value-of select="$datMeeting"/>
</p>
</xsl:when>
<xsl:otherwise>
<p>Available</p>
</xsl:otherwise>
</xsl:choose>
</xsl:otherwise>
</xsl:choose>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
I have been working on the IsAvailableMidweek template and in principle it works. The content it displays was for debugging purposes.
The challenge I have is that I want to display (this this specific case) the Chairman in a span as text. If he is determined as "Not Available" then I want to apply a class of NotAvailable to the span object.
I know how to display the value in a span. That is straightforward. But how do I adjust the template IsAvailableMidweek I have written so that it can apply this class if it determines the person is not available?
I hope this makes sense. I don't think I can use functions in with XSLT-1.
I don't know if this is the best way, but it appears to do what I am looking for:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msa="http://www.publictalksoftware.co.uk/msa">
<xsl:output method="html" indent="yes" version="4.01"
doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
doctype-public="//W3C//DTD XHTML 1.0 Transitional//EN"/>
<xsl:variable name="PubDB" select="document('MSA_PublisherDatabase.XML')"/>
<xsl:template match="/">
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title>Test</title>
</head>
<body>
<xsl:for-each select="MeetingWorkBook/Meeting">
<p>
<xsl:call-template name="SetClassName">
<xsl:with-param name="strName" select="Chairman"/>
</xsl:call-template>
<xsl:value-of select="Chairman"/>
</p>
</xsl:for-each>
</body>
</html>
</xsl:template>
<xsl:template name="SetClassName">
<xsl:param name="strName"/>
<xsl:variable name="thePublisher" select="$PubDB/msa:PublisherDatabase/msa:Publishers/msa:Publisher[msa:Name=$strName]"/>
<xsl:if test="$thePublisher">
<xsl:choose>
<xsl:when test="$thePublisher/msa:Availability/#Midweek='false'">
<xsl:attribute name="class">NotAvailable</xsl:attribute>
</xsl:when>
<xsl:otherwise>
<xsl:variable name ="datMonth" select="format-number(MeetingDate/#Month,'00')"/>
<xsl:variable name ="datDay" select="format-number(MeetingDate/#Day,'00')"/>
<xsl:variable name="datMeeting" select="concat(MeetingDate/#Year, '-', $datMonth, '-', $datDay)"/>
<xsl:choose>
<xsl:when test="$thePublisher/msa:Availability/msa:DatesNotAvailable[msa:Date=$datMeeting]">
<xsl:attribute name="class">NotAvailable</xsl:attribute>
</xsl:when>
<xsl:otherwise>
<!-- Available — Do Further Tests -->
</xsl:otherwise>
</xsl:choose>
</xsl:otherwise>
</xsl:choose>
</xsl:if>
</xsl:template>
</xsl:stylesheet>

XSLT 1.0 grouping example

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>

I want to split the string stored in a variable and store the obtained values in variable using xslt

<xsl:variable name="AAM" select="//AAM"/>
AAM will have string value_1,value_2,value_3,value_4
I then want to split this and store in 4 variables :
seg1,
seg2,
seg3,
seg4
Assuming the below as your input:
<?xml version="1.0" encoding="UTF-8"?>
<body>
<AAM>value_1,value_2,value_3,value_4</AAM>
</body>
An XSLT 2.0 solution to split a comma separated string can be:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" />
<xsl:variable name="AAM" select="//AAM" />
<xsl:template match="body">
<body>
<xsl:variable name="separator" select="','" />
<xsl:for-each select="tokenize($AAM,$separator)">
<xsl:element name="seg{position()}">
<xsl:value-of select="normalize-space(.)" />
</xsl:element>
</xsl:for-each>
</body>
</xsl:template>
http://xsltransform.net/6qaFCET/1
Edit: (Based on commented)
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" />
<xsl:variable name="AAM" select="//AAM" />
<xsl:template match="body">
<body>
<xsl:variable name="separator" select="','" />
<xsl:for-each select="tokenize($AAM,$separator)">
<xsl:choose>
<xsl:when test="position() = 1">
<xsl:variable name="seg1">
<xsl:value-of select="normalize-space(.)" />
</xsl:variable>
<xsl:copy-of select="$seg1" />
<xsl:text>
</xsl:text>
</xsl:when>
<xsl:when test="position() = 2">
<xsl:variable name="seg2">
<xsl:value-of select="normalize-space(.)" />
</xsl:variable>
<xsl:copy-of select="$seg2" />
<xsl:text>
</xsl:text>
</xsl:when>
<xsl:when test="position() = 3">
<xsl:variable name="seg3">
<xsl:value-of select="normalize-space(.)" />
</xsl:variable>
<xsl:copy-of select="$seg3" />
<xsl:text>
</xsl:text>
</xsl:when>
<xsl:when test="position() = 4">
<xsl:variable name="seg4">
<xsl:value-of select="normalize-space(.)" />
</xsl:variable>
<xsl:copy-of select="$seg4" />
<xsl:text>
</xsl:text>
</xsl:when>
</xsl:choose>
</xsl:for-each>
</body>
</xsl:template>
http://xsltransform.net/6qaFCET/2
Note: following lines can be avoided. It has been added to populate value of variables.
<xsl:copy-of select="$seg2" />
<xsl:text>
</xsl:text>
Assuming you have <AAM>value_1,value_2,value_3,value_4</AAM> and <xsl:variable name="AAM" select="//AAM"/> you can of course use e.g. <xsl:variable name="value-sequence" select="tokenize($AAM, ',')"/> and if then needed access e.g. $value-sequence[1], $value-sequence[2] and so on, thus if you know there are only four values you can declare <xsl:variable name="seq1" select="$value-sequence[1]"/>, <xsl:variable name="seq2" select="$value-sequence[2]"/> and so on. The tokenize function is part of XPath 2 and later so works with XSLT 2 or 3 processors like Saxon 9 or AltovaXML or XmlPrime.
Answering late.
Maybe this is not an exact solution. But this may help you.
This is how I'm able to split a string from an XML node into two variables using XSLT 1.0
<xsl:when test="NodeName">
<xsl:variable name="var" select="NodeName"/>
<xsl:variable name="var1" select="substring-before($var, '=')"/>
<xsl:variable name="var2" select="substring-after($var, '=')"/>
<xsl:value-of select="$var1"/>-
<xsl:value-of select="$var2"/>
</xsl:when>
For Further reference Click Here

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.