apply xslt to xml content - xslt

I am using xslt. My input file is
<table bnf_id="bnf_204272" colsep="1" frame="all" id="nzf_3865" otherprops="HRT Risk table" pgwide="1" rowsep="1"><title>HRT Risk</title><tgroup cols="8" colsep="1" rowsep="1"><colspec colname="col1" /><colspec colname="col2" /><thead><row><entry morerows="1" rowsep="1">Risk</entry><entry morerows="1" rowsep="1">Age range (years)</entry><entry colsep="1" nameend="col4" namest="col3" rowsep="1">Background incidence per 1000 women in Europe not using HRT</entry><entry colsep="1" nameend="col6" namest="col5" rowsep="1"><b>Additional</b>
cases per 1000 women using
<b>oestrogen only HRT</b>
(estimated)
</entry><entry colsep="1" nameend="col8" namest="col7" rowsep="1"><b>Additional</b>
cases per 1000 women using
<b>combined (oestrogen-progestogen) HRT</b>
(estimated)
</entry></row><row><entry>Over 5 years</entry><entry nameend="col8" namest="col1"><b>Note</b><p>Where background incidence or additional cases have not been included in the table, this indicates a lack of available data. NS indicates a non-significant difference</p><p>
Taken from MHRA/CHM (<i>Drug Safety Update</i>
2007;
<b>1</b>
(2): 2–6) available at
<xref format="html" href="http://www.mhra.gov.uk/drugsafetyupdate">
www.mhra.gov.uk/drugsafetyupdate
</xref></p></entry></row></tbody></tgroup></table>
My xslt is
<xsl:template match="tgroup">
<tr>
<xsl:if test="#cols">
<xsl:attribute name="cols">
<xsl:value-of select="#cols"/>
</xsl:attribute>
</xsl:if>
<xsl:if test="#colsep">
<xsl:attribute name="colsep">
<xsl:value-of select="#colsep"/>
</xsl:attribute>
</xsl:if>
<xsl:if test="#rowsep">
<xsl:attribute name="rowsep">
<xsl:value-of select="#rowsep"/>
</xsl:attribute>
</xsl:if>
<xsl:if test="#align">
<xsl:attribute name="align">
<xsl:value-of select="#align"/>
</xsl:attribute>
</xsl:if>
<xsl:for-each select="colspec">
<th>
<xsl:if test="#colwidth">
<xsl:attribute name="width">
<xsl:value-of select="#colwidth"/>
</xsl:attribute>
</xsl:if>
<xsl:if test="#colname">
<xsl:attribute name="colname">
<xsl:value-of select="#colname"/>
</xsl:attribute>
</xsl:if>
<xsl:if test="#align">
<xsl:attribute name="align">
<xsl:value-of select="#align"/>
</xsl:attribute>
</xsl:if>
<xsl:if test="#colsep">
<xsl:attribute name="colsep">
<xsl:value-of select="#colsep"/>
</xsl:attribute>
</xsl:if>
<xsl:if test="#colnum">
<xsl:attribute name="colnum">
<xsl:value-of select="#colnum"/>
</xsl:attribute>
</xsl:if>
</th>
</xsl:for-each>
</tr>
<xsl:apply-templates/>
But having the above code in same XSLT file, my second match for th is executed.
So i get the empty th like
<th></th>
But i need to insert the ... between the tags. How to solve it?

Couldn't you simply add the following xsl:if condition before the closing </th> tag?
<xsl:if test="#colnum">
<xsl:attribute name="colnum">
<xsl:value-of select="#colnum"/>
</xsl:attribute>
</xsl:if>
<xsl:if test="text() = ''">
<xsl:text>...</xsl:text>
</xsl:if>
</th>

Related

Create a attribute dynamically

I'm writing an xsl script in which I need to create the attribute dynamically.
Here is my sample code.
<Table BORDERLINESTYLE="solid" BOTTOMMARGIN="12" NOTEGROUPSPACING="single" CELLPADDING="0" CELLSPACING="0" WIDTH="504"></Table>
Here BORDERLINESTYLE may or may not be available to all Table tags. and I want the output to be something like this.
<table style="border-style:solid; border-margin:12px; width:504px"></table>
Here are 2 things that I've tried.
1. Creating attributes
<table>
<xsl:if test="./#BORDERLINESTYLE">
<xsl:attribute name="border" select="'1px solid'"/>
</xsl:if>
<xsl:if test="./#WIDTH">
<xsl:attribute name="width" select="concat(./#WIDTH, 'px')"/>
</xsl:if>
<xsl:if test="./#BOTTOMMARGIN">
<xsl:attribute name="border" select="'1px solid'"/>
</xsl:if>
<xsl:apply-templates/>
</table>
the output that I get is as below.
<table border="1px solid" width="504px">
2. Inline adding
<table style="width:{current()/#WIDTH,'px'}; border:{./#BORDERLINESTYLE}; margin-bottom: {./#BOTTOMMARGIN, 'px'}; margin-top:{./#TOPMARGIN, 'px'}; "></table>
and the output is as below with some blank values like margin-top
<table style="width:504 px; border:solid; margin-bottom: 12 px; margin-top:px; ">
How can I add styles to style based on the attributes provided in the XML?
I'm using XSLT2.0.
I would use something like this:
<xsl:if test="#BORDERLINESTYLE|#WIDTH|#BOTTOMMARGIN|#TOPMARGIN">
<xsl:attribute name="style">
<xsl:if test="#BORDERLINESTYLE">
<xsl:text>border:1px solid;</xsl:text>
</xsl:if>
<xsl:if test="#WIDTH">
<xsl:value-of select="concat('width:',#WIDTH, 'px;')"/>
</xsl:if>
<xsl:if test="#BOTTOMMARGIN">
<xsl:value-of select="concat('margin-bottom:',#BOTTOMMARGIN, 'px;')"/>
</xsl:if>
<xsl:if test="#TOPMARGIN">
<xsl:value-of select="concat('margin-top:',#TOPMARGIN, 'px;')"/>
</xsl:if>
</xsl:attribute>
</xsl:if>
And depending on the business rules for mapping those source-attributes to style attributes change the code accordingly.
Btw.: ./# is the same as #
Use if else Function
For Example
margin-top: {if(//#TOPMARGIN!=0) then {./#TOPMARGIN, 'px'} else '12px'}
I need to create the attribute dynamically.
Actually, you want to populate the attribute dynamically - which could be done by applying a template to each input attribute you want to use:
<xsl:template match="Table">
<table>
<xsl:attribute name="style">
<xsl:apply-templates select="#BORDERLINESTYLE | #BOTTOMMARGIN | #WIDTH"/>
</xsl:attribute>
</table>
</xsl:template>
<xsl:template match="#BORDERLINESTYLE">
<xsl:text>border-style:</xsl:text>
<xsl:value-of select="."/>
<xsl:text>; </xsl:text>
</xsl:template>
<xsl:template match="#BOTTOMMARGIN">
<xsl:text>border-margin:</xsl:text>
<xsl:value-of select="."/>
<xsl:text>px; </xsl:text>
</xsl:template>
<xsl:template match="#WIDTH">
<xsl:text>width:</xsl:text>
<xsl:value-of select="."/>
<xsl:text>; </xsl:text>
</xsl:template>

Add link in author label - DSpace 6.2

I've trying to edit item-view.xsl to add a link in author label (dc.contributor.author) but no luck yet.
I'm using XMLUI - Mirage2
Author link example image
in: https://openknowledge.worldbank.org/handle/10986/29498
What should I add?
Thanks
The following code snippet might help. This code turns the subject field into a facet link. It will require a little modification to work for the author field.
<xsl:variable name="H_SUBJECT">Subject</xsl:variable>
<xsl:variable name="DFILTER_SUBJECT">/discover?filtertype=subject&filter_relational_operator=equals&filter=</xsl:variable>
<xsl:template name="itemSummaryView-DIM-subject">
<xsl:if test="dim:field[#element='subject']">
<div class="simple-item-view-description item-page-field-wrapper table">
<h5><xsl:value-of select="$H_SUBJECT"/></h5>
<div>
<xsl:for-each select="dim:field[#element='subject']">
<xsl:choose>
<xsl:when test="node()">
<a class="gu-subject-link" href="{concat($FILTER_SUBJECT,.)}">
<span>
<xsl:apply-templates select="." mode="microtag-prop"/>
<xsl:apply-templates select="text()"/>
</span>
</a>
</xsl:when>
<xsl:otherwise>
<xsl:text> </xsl:text>
</xsl:otherwise>
</xsl:choose>
<xsl:if test="count(following-sibling::dim:field[#element='subject']) != 0">
<xsl:text>; </xsl:text>
</xsl:if>
</xsl:for-each>
<xsl:if test="count(dim:field[#element='subject']) > 1">
<xsl:text>; </xsl:text>
</xsl:if>
</div>
</div>
</xsl:if>
</xsl:template>

How to properly use the Muenchian for grouping a very repetitive tag by an element?

I am facing an issue using the Muenchian. I have a very large xml to transform into a new output. I've build the xsl to have a key using an element as the "parent" to group by, and everything to return as child. The source has many times the same Parent for different child, but it brings only the 1st one.
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<Calculate_Account_Level_S6>
<Account_Number_ANI_ID17>7700.401100.900</Account_Number_ANI_ID17>
<Description001_ID19>A/P ThirdParty</Description001_ID19>
<Parent_Account_Number_ANI_ID21>401100.900</Parent_Account_Number_ANI_ID21>
<DebitCreditAccount_ID26>A</DebitCreditAccount_ID26>
<Account_Group_Gen_ID28>MX2010101</Account_Group_Gen_ID28>
</Calculate_Account_Level_S6>
<Calculate_Account_Level_S6>
<Account_Number_ANI_ID17>7700100.401100.900</Account_Number_ANI_ID17>
<Description001_ID19>A/P ThirdParty</Description001_ID19>
<Parent_Account_Number_ANI_ID21>401100.900</Parent_Account_Number_ANI_ID21>
<DebitCreditAccount_ID26>A</DebitCreditAccount_ID26>
<Account_Group_Gen_ID28>MX2010101</Account_Group_Gen_ID28>
</Calculate_Account_Level_S6>
<Calculate_Account_Level_S6>
<Account_Number_ANI_ID17>7700101.401100.900</Account_Number_ANI_ID17>
<Description001_ID19>A/P ThirdParty</Description001_ID19>
<Parent_Account_Number_ANI_ID21>401100.900</Parent_Account_Number_ANI_ID21>
<DebitCreditAccount_ID26>A</DebitCreditAccount_ID26>
<Account_Group_Gen_ID28>MX2010101</Account_Group_Gen_ID28>
</Calculate_Account_Level_S6>
XSL KEY:
<xsl:key name="GrpParentAccount" match="/RLA70901/Generic_Char_of_Account_Generation_S5/Calculate_Account_Level_S6" use="Parent_Account_Number_ANI_ID21" />
<xsl:key name="Account" match="/RLA70901/Generic_Char_of_Account_Generation_S5/Calculate_Account_Level_S6" use="Account_Number_ANI_ID17" />
Coding:
<xsl:for-each select="/RLA70901/Generic_Char_of_Account_Generation_S5/Calculate_Account_Level_S6[count(. | key('GrpParentAccount', Parent_Account_Number_ANI_ID21)[1]) = 1]">
<xsl:sort select="Parent_Account_Number_ANI_ID21"/>
<xsl:sort select="Account_Number_ANI_ID17"/>
<catalogocuentas:Ctas>
<xsl:attribute name="CodAgrup">
<xsl:value-of select="substring(Account_Group_Gen_ID28,3.0,3.0)"/>
</xsl:attribute>
<xsl:attribute name="NumCta">
<xsl:value-of select="Parent_Account_Number_ANI_ID21"/>
</xsl:attribute>
<xsl:attribute name="Desc">
<xsl:value-of select="Converted_Account_Description_ID29"/>
</xsl:attribute>
<xsl:attribute name="SubCtaDe">
<xsl:text disable-output-escaping="no"></xsl:text>
</xsl:attribute>
<xsl:attribute name="Nivel">
<xsl:text disable-output-escaping="no">1</xsl:text>
</xsl:attribute>
<xsl:attribute name="Natur">
<xsl:value-of select="DebitCreditAccount_ID26"/>
</xsl:attribute>
</catalogocuentas:Ctas>
<!-- Grouping End -->
<!-- Printing All Accounts by Group -->
<xsl:for-each select="/RLA70901/Generic_Char_of_Account_Generation_S5/Calculate_Account_Level_S6[count(. | key('Account', Account_Number_ANI_ID17)[1]) = 1]">-->
<catalogocuentas:Ctas>
<xsl:attribute name="CodAgrup">
<xsl:value-of select="substring(Account_Group_Gen_ID28,3.0,5.0)"/>
</xsl:attribute>
<xsl:attribute name="NumCta">
<xsl:value-of select="Account_Number_ANI_ID17"/>
</xsl:attribute>
<xsl:attribute name="Desc">
<xsl:value-of select="Converted_Account_Description_ID29"/>
</xsl:attribute>
<xsl:if test='Parent_Account_Number_ANI_ID21 != ""'>
<xsl:attribute name="SubCtaDe">
<xsl:value-of select="Parent_Account_Number_ANI_ID21"/>
</xsl:attribute>
</xsl:if>
<xsl:attribute name="Nivel">
<xsl:text disable-output-escaping="no">2</xsl:text>
</xsl:attribute>
<xsl:attribute name="Natur">
<xsl:value-of select="DebitCreditAccount_ID26"/>
</xsl:attribute>
</catalogocuentas:Ctas>
</xsl:for-each>
</xsl:for-each>
</catalogocuentas:Catalogo>
<catalogocuentas:Ctas CodAgrup="201" NumCta="401100.900" Desc="Proveedores IVA 16%" SubCtaDe="" Nivel="1" Natur="A"/><catalogocuentas:Ctas CodAgrup="20101" NumCta="7700.401100.900" Desc="Proveedores IVA 16%" SubCtaDe="401100.900" Nivel="2" Natur="A"/></catalogocuentas:Catalogo>
I was expecting to print all Calculate_Account_Level_S6/Account_Number_ANI_ID17 by the Calculate_Account_Level_S6/Parent_Account_Number_ANI_ID21 Any help is very WELCOME !!! :)
Try changing the second key from
<xsl:key name="Account" match="/RLA70901/Generic_Char_of_Account_Generation_S5/Calculate_Account_Level_S6" use="Account_Number_ANI_ID17" />
to
<xsl:key name="Account" match="/RLA70901/Generic_Char_of_Account_Generation_S5/Calculate_Account_Level_S6" use="concat(Account_Number_ANI_ID17, '|', Account_Number_ANI_ID17)" />
and the inner for-each from
<xsl:for-each select="/RLA70901/Generic_Char_of_Account_Generation_S5/Calculate_Account_Level_S6[count(. | key('Account', Account_Number_ANI_ID17)[1]) = 1]">
to
<xsl:for-each select="key('GrpParentAccount', Parent_Account_Number_ANI_ID21)[count(. | key('Account', concat(Account_Number_ANI_ID17, '|', Account_Number_ANI_ID17))[1]) = 1]">

XSLT setting a variable to either foo or #foo depending on presence of attribute

I'm trying to set parttext to #head if use_head="true" is not present and to the contents of <head> </head> if use_head="true" is present
<xsl:template match="toc_part">
<xsl:variable name="artnum">
<xsl:value-of select="../#num" />
</xsl:variable>
<xsl:variable name="partnum">
<xsl:value-of select="#num" />
</xsl:variable>
<xsl:variable name="parttext">
<xsl:if test="#use_head">
<xsl:value-of select="head"/>
</xsl:if>
<xsl:if test="not[#use_head]">
<xsl:value-of select="#head"/>
</xsl:if>
</xsl:variable>
<tr>
<td>
 
</td>
<td>
<a class="int" href="{$GBLfilePre}{$artnum}.html#{$artnum}{$partnum}"><xsl:text>Part </xsl:text><xsl:value-of select="$partnum" /></a>
</td>
<td>
<xsl:value-of select="$parttext" />
</td>
</tr>
</xsl:template>
I've also tried:
<xsl:if test="#use_head"><xsl:variable name="parttext"><xsl:value-of select="head"></xsl:variable>
<xsl:if test="not[#use_head"]><xsl:variable name="parttext"><xsl:value-of select="#head"></xsl:variable>
which give parttext undefined when referenced.
Try:
<xsl:variable name="parttext">
<xsl:choose>
<xsl:when test="#use_head='true'">
<xsl:value-of select="head"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="#head"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
Your current test in the first if statement will evaluate to true() if the #use_head attribute exists, regardless of it's value. If you want the test to evaluate whether or not it's value is equal to "true" you should use test="#use_head='true'".
The second if statement is evaluating whether or not there is an element named "not" that has an attribute called "use_head", because the square brackets are a predicate. I believe you had intended to use the not() function: not(#use_head='true')
You could then use an <xsl:choose> instead of two if blocks:
<xsl:variable name="parttext">
<xsl:choose>
<xsl:when test="#use_head='true'">
<xsl:value-of select="head"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="#head"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
In XSLT 2.0:
<xsl:variable name="head"
select="if (#use_head='true') then head else #head"/>
In XSLT 1.0, either Hansen's solution, or
<xsl:variable name="head"
select="head[current()/#use_head='true'] |
#head[not(current()/#use_head='true')]"/>
In future, please tell us which version of XSLT you are using. One can sort of guess this must be XSLT 1.0 because in 2.0 the solution is trivial, but it's better not to have to guess.

How to check whether a node is present in the file or not

I have xml which could have sometimes node DSD_G22 but not always. SO if that node is present then get the value of the elements otherwise assign empty:
input 1 scenario:
<root>
<G_83>
<G_8301/>
<G_8302/>
</G_83>
<DSD_G22>
<DSD_G22_G2201>Value</DSD_G22_G2201>
<DSD_G22_G2202>Value1</DSD_G22_G2202>
</DSD_G22>
</root>
Scenario Input 2:
<root>
<G_83>
<G_8301/>
<G_8302/>
</G_83>
</root>
The output for scenario 2 should be:
<G_83>
<G_8301/>
<G_8302/>
</G_83>
<DSD_G22>
<DSD_G22_G2201/>
<DSD_G22_G2202/>
<DSD_G22/>
</root>
I tried to do this but doesn't work. Please HelP:
<xsl:variable name="emptySpace" select="' '" />
<xsl:if test="#DSD_G22">
<xsl:if test="#DSD_G22_G2201">
<xsl:attribute name="DSD_G22_G2201">
<xsl:value-of select="#DSD_G22_G2201" />
</xsl:attribute>
</xsl:if>
<xsl:if test="#DSD_G22_G2202">
<xsl:attribute name="DSD_G22_G2202">
<xsl:value-of select="#DSD_G22_G2202" />
</xsl:attribute>
</xsl:if>
</xsl:if>
<xsl:if test="not(#DSD_G22)">
<xsl:attribute name="DSD_G22_G2201">
<xsl:value-of select="#emptySpace " />
</xsl:attribute>
<xsl:attribute name="DSD_G22_G2202">
<xsl:value-of select="#emptySpace" />
</xsl:attribute>
</xls:if>
This would do it for you:
<DSD_G22>
<DSD_G22_G2201><xsl:value-of select="DSD_G22/DSD_G22_G2201"/></DSD_G22_G2201>
<DSD_G22_G2202><xsl:value-of select="DSD_G22/DSD_G22_G2202"/></DSD_G22_G2202>
</DSD_G22>
<xsl:if test="count(DSD_G22) > 0">
Exists!
</xsl:if>