Unwanted spacing between nested elements - how to select all descendants, except one - xslt

I am completely new with XSLT, thank you in advance for your understanding. I need to prepare an xml which will be sent to Adobe InDesign server. In html files (which represent my input that I need to transform to xml and send to Adobe InDesign by using XSLT transformation), I've got the following list:
<li>IV <span><span>nitroglycerin</span></span> may be of short-term benefit by decreasing preload and afterload by dilating peripheral capacitance and resistance vessels on vascular smooth musculature (IV 10 to 20 <i>μ</i>g/min, increase up to 200 <i>μ</i>g/min) <span>1</span><span>B</span>.</li>
The main template that I am using for the transformation is:
<xsl:template match="li[not(descendant::p) and not(ancestor::section[#class='references' or #class='References'])]" mode="li-pass1">
<xsl:variable name="depth" select="count(ancestor::li) + 1"/>
<xsl:variable name="listType">
<xsl:choose>
<xsl:when test="parent::ol">
<xsl:value-of select="'NL'"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="'BL'"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<ParagraphStyleRange AppliedParagraphStyle="ParagraphStyle/{$listType}{if ($depth eq 1) then '' else $depth}">
<Content>
<xsl:value-of select="(text() | descendant::span/text() | descendant::i/text())/normalize-space()"/>
</Content>
<Br/>
</ParagraphStyleRange>
</xsl:template>
But with the solution, I got this unwanted effect:
<Content>IV nitroglycerin may be of short-term benefit by decreasing preload and afterload by dilating peripheral capacitance and resistance vessels on vascular smooth musculature (IV 10 to 20 μ g/min, increase up to 200 μ g/min) 1 B .</Content>
So, each "i" or "span" tag (from the input) creates a new spacing, which should not appear between the characters in "μg" or "1B", for example. I probably need to somehow rewrite my select, right? I wanted to select descendant-or-self::*/text(), but I didn't want to include descendant::li. I'm not sure how to do that.
Desired output is the following one:
<Content>IV nitroglycerin may be of short-term benefit by decreasing preload and afterload by dilating peripheral capacitance and resistance vessels on vascular smooth musculature (IV 10 to 20 μg/min, increase up to 200 μg/min) 1B.</Content>
Thank you in advance for any help.
UPDATE:
Let me explain the issue better. This is an input list that I need to transform:
<ul>
<li>Two potential pathophysiologic conditions lead to the clinical findings of HF, namely systolic and/or diastolic heart dysfunction.
<ul>
<li>Systolic dysfunction: an <i>inotropic</i> abnormality, due to myocardial infarction (MI) or dilated or ischemic cardiomyopathy (CM), resulting in diminished systolic emptying (ejection fraction <45%).</li>
<li>Diastolic dysfunction: a <i>compliance</i> abnormality, due to hypertensive CM, in which ventricular relaxation is impaired (ejection fraction >45%), resulting in decreased filling.</li>
<li>In an attempt to adopt a more pragmatic classification system, one that has been accepted by both the European and American HF guidelines, the terms HF with reduced, midrange, or preserved LVEF (HFrEF, HFmrEF, and HFpEF, respectively) have been adopted recently.</li>
</ul> </li> </ul>
What I am getting is:
<ParagraphStyleRange AppliedParagraphStyle="ParagraphStyle/BL">
<CharacterStyleRange AppliedCharacterStyle="CharacterStyle/$ID/[No character style]">
<Content>Two potential pathophysiologic conditions lead to the clinical findings of HF, namely systolic and/or diastolic heart dysfunction. inotropic compliance</Content>
<Br/>
</CharacterStyleRange>
</ParagraphStyleRange>
<ParagraphStyleRange AppliedParagraphStyle="ParagraphStyle/BL2">
<CharacterStyleRange AppliedCharacterStyle="CharacterStyle/$ID/[No character style]">
<Content>Systolic dysfunction: an  inotropic  abnormality, due to myocardial infarction (MI) or dilated or ischemic cardiomyopathy (CM), resulting in diminished systolic emptying (ejection fraction <45%).</Content>
<Br/>
</CharacterStyleRange>
</ParagraphStyleRange>
<ParagraphStyleRange AppliedParagraphStyle="ParagraphStyle/BL2">
<CharacterStyleRange AppliedCharacterStyle="CharacterStyle/$ID/[No character style]">
<Content>Diastolic dysfunction: a  compliance  abnormality, due to hypertensive CM, in which ventricular relaxation is impaired (ejection fraction >45%), resulting in decreased filling.</Content>
<Br/>
</CharacterStyleRange>
</ParagraphStyleRange>
A desired result should not contain additional spacing between "italic" and "span" tags (the words "inotropic" and "compiliance" for example). And also, I do not want to have "inotropic" and "compiliance" words within the text:"Two potential pathophysiologic conditions lead to the clinical findings of HF, namely systolic and/or diastolic heart dysfunction. inotropic compliance", because those come from the descendants of "li" elements, and don't belong to the first "li". So, what I would like to get is:
<ParagraphStyleRange AppliedParagraphStyle="ParagraphStyle/BL">
<CharacterStyleRange AppliedCharacterStyle="CharacterStyle/$ID/[No character style]">
<Content>Two potential pathophysiologic conditions lead to the clinical findings of HF, namely systolic and/or diastolic heart dysfunction.</Content>
<Br/>
</CharacterStyleRange>
</ParagraphStyleRange>
<ParagraphStyleRange AppliedParagraphStyle="ParagraphStyle/BL2">
<CharacterStyleRange AppliedCharacterStyle="CharacterStyle/$ID/[No character style]">
<Content>Systolic dysfunction: an inotropic abnormality, due to myocardial infarction (MI) or dilated or ischemic cardiomyopathy (CM), resulting in diminished systolic emptying (ejection fraction <45%).</Content>
<Br/>
</CharacterStyleRange>
</ParagraphStyleRange>
<ParagraphStyleRange AppliedParagraphStyle="ParagraphStyle/BL2">
<CharacterStyleRange AppliedCharacterStyle="CharacterStyle/$ID/[No character style]">
<Content>Diastolic dysfunction: a compliance abnormality, due to hypertensive CM, in which ventricular relaxation is impaired (ejection fraction >45%), resulting in decreased filling.</Content>
<Br/>
</CharacterStyleRange>
</ParagraphStyleRange>
Thank you for any help once again.

Related

XSLT 2.0 co-ordinating multiple modes

XSLT 2.0, stylesheet and data at https://xsltfiddle.liberty-development.net/bFDb2D3/4
I am transforming medieval documents encoded in tei-xml into webpages where the user can toggle between two different views of the documents, as well as see the translation and various footnotes (eg). This requires multiple layers of processing to output:
Two latin versions ('inter' and 'diplo') between which the user can toggle (derived from the same tei markup)
Translated version with almost no transformations (just paragraph formatting and italics)
Critical apparatus using footnoting # a, b, c, etc.
Historical footnotes using footnoting # 1, 2, 3, etc.
I am using modes in order to handle the levels of processing, and each mode on its own works fine, but together they are missing outputs.
What should output:
<div class="inter"><p> with all transformations mode inter + fn-add-marker
[this should contain <a href>, superscript letters and numbers in text]
<div class="diplo"><p> with all transformations mode diplo + fn-add-marker
[this should contain [text] , line numbers, superscript letters and numbers in text]
<div><p> with translations
<div> with critical apparatus
<div> with footnotes
The XSLTfiddle output is:
URL and superscript letters ok! missing superscript numbers (mode fn-add-marker)
Superscript letters ok! Line # and [text] ok except where inside <persName> or <placeName> (ie.<xsl:template match="tei:lb"> <xsl:template match="tei:supplied">) and missing superscript numbers (mode fn-add-marker)
ok!
ok!
ok!
With respect to #2, the missing line # and [text] appear to be a result of the templates that treat <persName> and <placeName> not handing off to other templates? (templates at lines 173-218)
All templates concerning mode fn-add-marker are at lines 41-77.
Many thanks in advance.
Basically in XSLT 2, once you work with named modes, you need to make sure in a template belonging to a certain mode, having e.g. mode="foo", that you use e.g. mode="foo" or more general mode="#current" on any xsl:apply-templates inside to ensure processing continues in that mode. See https://www.w3.org/TR/xslt20/#element-apply-templates for details.
At https://xsltfiddle.liberty-development.net/gWmuiK7 I have tried XSLT to fix your stylesheet and then at https://xsltfiddle.liberty-development.net/bFDb2D3/5 you can see the result of applying the fixed stylesheet. Not sure whether that programmatic approach is the right tool but it might help to demonstrate the suggested use mode mode on xsl:apply-templates.
Then I think you need to make sure you process the added markers in the two new modes:
<!-- adds fn numbers -->
<xsl:template match="tei:date[#type='deposition_date']" mode="inter dilpo">
<xsl:apply-templates mode="#current"/>
<xsl:apply-templates select="." mode="number"/>
</xsl:template>
<xsl:template match="tei:note[#type='public'] | tei:fn-marker" mode="inter diplo">
<xsl:apply-templates select="." mode="number"/>
</xsl:template>
<xsl:template match="tei:date[#type='deposition_date'] | tei:note[#type='public'] | tei:fn-marker" mode="number">
<sup>
<xsl:number count="tei:date[#type='deposition_date'] | tei:note[#type='public'] | tei:fn-marker" format="1" level="any"/>
</sup>
</xsl:template>
<!-- end of footnote transformations -->
https://xsltfiddle.liberty-development.net/bFDb2D3/6 lines 51 to 66.

Cycle through xsl:key, output results, add delimiter - but skipping some results

I have an xsl:key that I am using with a large text-based XML file, using XSL 3 processed by Saxon.
<xsl:key name="getcommonseg" match="seg[#master-id]" use="#master-id"/>
This key is passed against thousands of elements that look like this:
<seg id="unique_id_here" master-id="master-id_here">
The #master-id is actually one of the #ids that 'groups' a number of <seg> together. For example:
<seg id="1-A" master-id="1-A"/>
<seg id="1-G" master-id="1-A"/>
<seg id="2-G" master-id="2-G"/>
<seg id="10-Y" master-id="1-A"/>
<seg id="5-C"/>
<seg id="6-B" master-id="2-G"/>
<seg id="8-R"/>
<seg id="11-K" master-id="2-G"/>
<seg id="19-D" master-id="1-A"/>
<seg id="22-T" master-id="2-G"/>
[...]
When I am reporting any given <seg>, I use the <xsl:key> to find the rest any related <seg>. For example, if I am positioned on:
<seg id="11-K" master-id="2-G"/>
I apply the key, and then cycle through the returned records, output them separated by a comma, and reject the record that is the current record:
<template match="seg[#commonid]">
<xsl:variable name="masterid" select="./#master-id"/>
<xsl:variable name="currentid" select="./#id"/>
<xsl:value-of select="'Seg' || ./#id || 'corresponds to the following seg id(s): ' "/>
<xsl:for-each select="key('getcommonseg',$masterid)">
<xsl:if test="./#id != $currentid">
<xsl:value-of select="./#id"/>
<xsl:if test="position() != last()">, </xsl:if>
</xsl:if>
</xsl:for-each>
</template>
This outputs:
Seg 11-K corresponds to the following seg id(s): 2-G, 6-B, 22-T
As you can see it doesn't output value '11-K' and adds commas appropriately. However, if the position was:
<seg id="22-T" master-id="2-G"/>
It would output:
Seg 22-T corresponds to the following seg id(s): 2-G, 6-B, 11-K,
...adding the last comma inadvertently.
How can I avoid this problem of the final comma when the last node is skipped/rejected?
Thanks in advance.
As you are using XSLT 2 or 3 you should simply use <xsl:value-of select="(key('getcommonseg', #master-id) except .)/#id" separator=", "/>, instead of "cycling".

Need to remove Note: from the start of a string using XSLT

I have been tasked with styling XML and so far nearly all of the tags I have been given are either p or ph which just display the contents of the tag on screen and I can style as required
eg:
<p outputclass="LC AStatProv">Council Regulation (EC) No 2201/2003 of 27 November 2003 Concerning Jurisdiction and the Recognition and Enforcement of Judgments in Matrimonial Matters and in Matters of Parental Responsibility, repealing Regulation (EC) No 1347/2000 (Brussels II Revised) (2003) OJ L 338/1, Art 20</p>
will display as:
Council Regulation (EC) No 2201/2003 of 27 November 2003 Concerning Jurisdiction and the Recognition and Enforcement of Judgments in Matrimonial Matters and in Matters of Parental Responsibility, repealing Regulation (EC) No 1347/2000 (Brussels II Revised) (2003) OJ L 338/1, Art 20
Today I have noticed that a new note tag has been used and this is causing "Note: " to be prepended to the beginning of each string eg:
<p outputclass="LC ACourt"><note outputclass="CaseSearchCourt">Court of Appeal</note></p>
will display as:
Note: Re A (Abduction: Interim Directions: Accommodation by Local Authority) [2010] EWCA Civ 586 [2011] 1 FLR 1
The FO produced for this is:
<fo:block><fo:inline font-weight="bold" border-right-width="0pt" border-left-width="0pt">Note: </fo:inline> Court of Appeal</fo:block>
I have tried the following code gleaned from elsewhere on this site but it didn't remove the string I wanted:
<xsl:template match="note">
<note>
<xsl:if test="contains(., 'Note:')">
<xsl:call-template name="remove">
<xsl:with-param name="value" select="."/>
</xsl:call-template>
</xsl:if>
</note>
</xsl:template>
<xsl:template name="remove">
<xsl:param name="value"/>
<xsl:value-of select="concat(substring-before($value, 'Note:'), substring-after($value, 'Note:'))"/>
</xsl:template>
I have tried to see where XSLT gets the "Note: " from but can't find it anywhere so my next thought is to try and pattern match the string and remove "Note: " from the beginning of the string. Is this a good way to go about this and how would I do this?
thanks.
EDIT: Just to summarise my rambling and confusing question.
Where it renders:
Note: Re A (Abduction: Interim Directions: Accommodation by Local Authority) [2010] EWCA Civ 586 [2011] 1 FLR 1
I just want it to render:
Re A (Abduction: Interim Directions: Accommodation by Local Authority) [2010] EWCA Civ 586 [2011] 1 FLR 1
EDIT 2 and the answer
My initial investigations were based upon grepping for Note: which wasn't being found. I have though found the following:
<xsl:template match="*[contains(#class,' topic/note ')]">
and then commented out the following lines:
<!--<xsl:text>Note</xsl:text>-->
</xsl:otherwise>
</xsl:choose>
<!--<xsl:text>: </xsl:text>-->
</fo:inline>
<xsl:text> </xsl:text>
<xsl:apply-templates/>
And I have got rid of the "Note: ".
EDIT 3:
This didn't actually work as it created an opening block but didn't close it so I ended up removing the entire <xsl:template match="*[contains(#class,' topic/note ')]"> as we have no need for any type of notes in our system
This didn't actually work as it created an opening block but didn't close it so I ended up removing the entire <xsl:template match="*[contains(#class,' topic/note ')]"> as we have no need for any type of notes in our system

Paragraph needs to have 2lines or 3lines of sentences not just one line [duplicate]

This question already exists:
Closed 11 years ago.
Possible Duplicate:
In my xml feed i have … … replace it with period. and space & also i need to <p> tag after every two or three senctences using xsl
This is XML:
<data>The production of opium itself has basically not changed since
ancient times...Opium trade became more regular by the seventeenth
century, when it was mixed with tobacco for smoking, and addiction was
first recognized... This is a test Message3…This is showing off a
handful of updates to its line of audio accessories this week at IFA
in Berlin. At top of the list is the newly revealed inAir 5000, a
hefty tabletop AirPlay speaker that the company is firmly positioning
to take on Bowers&Wilkins' Zeppelin line (which also recently got its
own AirPlay version)... Like that system, the inAir certainly offers a
unique take on aesthetics, with a teardrop design. The company opted
not to install an Apple dock on the 110 watt system, given that
compatible devices can stream audio wirelessly to the thing via
AirPlay...Twice a month, tourists board a bus and embark on a "fact-finding mission" to one of the hottest spots in the immigration debate -- the Arizona-Mexico border. Tourists are encouraged to make make up their own minds..."Contagion" is an action-thriller about the pandemic outbreak of a deadly virus. It is part fantasy, part reality and totally possible, says one global health expert...The families are trying to raise the bail money.</data>
using xsl
Paragraph needs to split into three equal lines,but not just one like and one another thing is i need to remove '...', '…' and replace it with just period.
<p>This is showing off a handful of updates to its line of audio accessories this week at IFA in Berlin. At top of the list is the newly revealed inAir 5000, a hefty tabletop AirPlay speaker that the company is firmly positioning to take on Bowers&Wilkins' Zeppelin line (which also recently got its own AirPlay version).</p>
<p>Like that system, the inAir certainly offers a unique take on aesthetics, with a teardrop design. The company opted not to install an Apple dock on the 110 watt system, given that compatible devices can stream audio wirelessly to the thing via AirPlay.Twice a month, tourists board a bus and embark on a "fact-finding mission" to one of the hottest spots in the immigration debate -- the Arizona-Mexico border. Tourists are encouraged to make make up their own minds.</p>
"Contagion" is an action-thriller about the pandemic outbreak of a deadly virus. It is part fantasy, part reality and totally possible, says one global health expert.The families are trying to raise the bail money.
I hope this answer is what you need:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" />
<xsl:template match="/">
<xsl:variable name="count" select="string-length(.)"/>
<xsl:variable name="firstparagraph" select="substring(., 1, string-length(.)-($count*0.67))"/>
<xsl:variable name="afterfirstparagraph" select="substring-after(., $firstparagraph)"/>
<xsl:variable name="countafterfirstparagraph" select="string-length($afterfirstparagraph)"/>
<xsl:variable name="secondparagraph" select="substring($afterfirstparagraph, 1, string-length($afterfirstparagraph)-($countafterfirstparagraph*0.5))"/>
<xsl:element name="data">
<xsl:element name="p">
<xsl:value-of select="replace(replace(substring(., 1, string-length(.)-($count*0.67)), '\.\.\.', '.'), '…', '.')"/>
</xsl:element>
<xsl:element name="p">
<xsl:value-of select="replace(replace(substring($afterfirstparagraph, 1, string-length($afterfirstparagraph)-($countafterfirstparagraph*0.5)), '\.\.\.', '.'), '…', '.')"/>
</xsl:element>
<xsl:element name="p">
<xsl:value-of select="replace(replace(substring-after(., $secondparagraph), '\.\.\.', '.'), '…', '.')"/>
</xsl:element>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
Please note that you have to replace "&" with its unicode.

How Can I Reduce "When" Statement in XSLT

Hello I am writing a XSLT statement where I need to implement 1500 conditional statements like -
<xsl:when test="ID = '51'">
<br>
<xsl:text>background: url('rightcolumn_seniorliv.jpg') no-repeat;</xsl:text>
<br>
</xsl:when>
<br>
<xsl:when test="ID = '52'">
<br>
<xsl:text>background: url('rightcolumn_seniorliv.jpg') no-repeat;</xsl:text>
<br>
</xsl:when>
If i write statement like this way then my pages will be very slow. How can i reduce my code and write this statement in a smart way?
<xsl:variable name="idlist">
<ids>
<id>50</id>
<id>59</id>
<id>66</id>
...
</ids>
</xsl:variable>
<xsl:key name="idk" match="id" use="."/>
<xsl:when test="key('idk', ID, $idlist)">...
This is XSLT 2.0 but can be adapted to work with 1.0.
I can't see all your cases, but if the pattern from your first two continues and you want that same 'rightcolumn_seniorliv.jpg' for IDs 51 thru 1551 then
<xsl: when test="ID>'50' and ID<'1552'">
it sounds like these ID cases are going well beyond logic and into the data realm. i obviously dont know anything about your app, but perhaps an ID to imagename mapping somewhere (probably database) would be in order. depending on what process generates the XML file (the first one, before XSLT transformation), you might want to just set the image name (or lack thereof) explicitly thru this mapping. then lose the when all together