Input:
<list list-type="simple" specific-use="front">
<list-item><p>Preface <xref rid="b-9781783084944-FM-001" ref-type="sec">00</xref></p></list-item>
<list-item><p>Series Title <xref rid="b-9781783084944-FM-003" ref-type="sec">00</xref></p></list-item>
<list-item><p>Dedication</p></list-item>
<list-item><p>Acknowledgments <xref rid="b-9781783084944-FM-005" ref-type="sec">00</xref></p></list-item>
<list-item><p>Contributors <xref rid="b-9781783084944-FM-006" ref-type="sec">00</xref></p></list-item>
<list-item><p>Glossary <xref rid="b-9781783084944-FM-008" ref-type="sec">00</xref></p></list-item>
</list>
I need output lik below
<div class="pagebreak" id="b-9781783084944-FM-002">
<h2 class="PET">CONTENTS</h2>
<div class="TocPrelims">Preface</div>
<div class="TocPrelims">Series Title </div>
</div>
My xslt:
<xsl:template match="list[#specific-use='front'][#list-type='simple']/list-item/p">
<div class="TocPrelims">
<a>
<xsl:attribute name="href">
<xsl:text>#toc</xsl:text>
<xsl:copy-of select="//list[#specific-use='front'][#list-type='simple']/list-item/p/xref[#rid]"/>
</xsl:attribute>
<xsl:apply-templates/>
</a>
</div>
</xsl:template>
Above coding of mine is not correct.. pls give suggestions.
You have a problem with this line:
<xsl:copy-of select="//list[#specific-use='front'][#list-type='simple']/list-item/p/xref[#rid]"/>
Firstly, the condition will select all xref elements, but you only need the one for the current p you are positioned on. Secondly, it is selecting the xref element if it has an rid attribute, but you actually want to select the rid attribute. You also really want to use xsl:value-of here
<xsl:value-of select="xref/#rid"/>
Try this template instead:
<xsl:template match="list[#specific-use='front'][#list-type='simple']/list-item/p">
<div class="TocPrelims">
<a>
<xsl:attribute name="href">
<xsl:text>#toc</xsl:text>
<xsl:value-of select="xref/#rid"/>
</xsl:attribute>
<xsl:value-of select="text()[1]" />
</a>
</div>
</xsl:template>
In fact, you can make use of Attribute Value Templates to simplify it to this:
<xsl:template match="list[#specific-use='front'][#list-type='simple']/list-item/p">
<div class="TocPrelims">
<a href="#toc{xref/#rid}">
<xsl:value-of select="text()[1]" />
</a>
</div>
</xsl:template>
Related
I need to remove the child element on the bases of the value of an id attribute. If there is no value in id attribute or there is no id attribute at all in contentblock tag then just remove the element and parent element will remain same if present. Also if content block is direct child of root and that content block doesn't have value in id attribute or there is no id attribute then remove that element also.
Example:
<root>
<div>
<contentblock class="align-center" id="" />
</div>
<p>
<contentblock class="align-center" />
</p>
<h2>
<contentblock class="align-center" id="623a7a1f87dd1975ce084ac7"/>
</h2>
<contentblock class="align-center" id=""/>
<contentblock class="align-center" id="623a7a1f87dd1975ce084ac7"/>
<contentblock class="align-center"/>
</root>
Expected Result:
<root>
<div>
</div>
<p>
</p>
<h2>
<contentblock class="align-center" id="623a7a1f87dd1975ce084ac7"/>
</h2>
<contentblock class="align-center" id="623a7a1f87dd1975ce084ac7"/>
</root>
Thanks in advance for the help.
What i tried but didn't give the expected result:
<!--<xsl:template match="contentblock[not(parent::root)] | contentblock[(parent::root)]">-->
<!--<xsl:choose>-->
<!-- <xsl:if test="contentblock/#id[string-length(.) =0]">-->
<!-- <xsl:apply-templates/>-->
<!-- </xsl:if>-->
<!--</xsl:choose>-->
<!--</xsl:template>-->
Another try:
<xsl:template match="div[contentblock] | p[descendant::contentblock] | h2[descendant::contentblock] | h3[descendant::contentblock]">
<xsl:choose>
<xsl:when test="contentblock[#id!='']">
<xsl:apply-templates/>
</xsl:when>
</xsl:choose>
<xsl:choose>
<xsl:when test="contentblock[#id=''] | contentblock[not(#id)]">
<xsl:copy> <xsl:apply-templates select="#*"/></xsl:copy>
</xsl:when>
</xsl:choose>
</xsl:template>
I can't match <xsl:template match="contentblock[not(parent::root)]"> as it performs the transformation on content block element itself which gives me different result. And also above solution does not work when i get the xml like this. When contentblock have multiple level parents like here it's p and span are parents of contentblock.
<p id="5c3692c8af8fe1f061518abc">
<span bulb-font-face="museo-sans, sans-serif">
<contentblock class="align-center block-full-width" id="5c3686fdcb7de304cd51696f" />
</span>
</p>
This template would match contentblock elements with an id attribute that has some value:
<xsl:template match="contentblock[#id!='']"/>
You would have to apply this template to all relevant contentblock elements, and in the template you would have to return whatever you want to return, like
<xsl:copy-of select="."/>
The data comes from the server, usually two rows, but sometimes it's more. So I try to make the list dynamic change.
<xsl:template match="Event">
<ul class="lines">
<xsl:apply-templates select="Line"/>
</ul>
</xsl:template>
<xsl:template match="Line">
<li class="something">
<a href="">
<span class="result"><xsl:value-of select="#result"/></span>
<span class="odds"><xsl:value-of select="#odds"/></span>
</a>
</li>
</xsl:template>
I have to count the number of "li" and if it's more than 2, i have to change the class of "li"
Within the template matching Line you can access the total number of Line elements within this Event using the last() function (which returns the index number of the last node in the "current node list" determined by the select expression of the apply-templates that caused this template to fire, which in this case is the set of Line children of a particular Event).
<li>
<xsl:attribute name="class">
<xsl:choose>
<xsl:when test="last() <= 2">something</xsl:when>
<xsl:otherwise>somethingElse</xsl:otherwise>
</xsl:choose>
</xsl:attribute>
How about something like this:
<xsl:template match="Event">
<ul class="lines">
<xsl:apply-templates select="Line"/>
</ul>
</xsl:template>
<xsl:template match="Line" name="Line">
<xsl:param name="classVal" select="'something'" />
<li class="{$classVal}">
<a href="">
<span class="result">
<xsl:value-of select="#result"/>
</span>
<span class="odds">
<xsl:value-of select="#odds"/>
</span>
</a>
</li>
</xsl:template>
<xsl:template match="Line[count(../Line) > 1]">
<xsl:call-template name="Line">
<xsl:with-param name="classVal" select="'somethingElse'" />
</xsl:call-template>
</xsl:template>
I have the following XML
<title>
This is a <highlight>test</highlight> thanks.
</title>
and want to convert into
<span class="title">this is a <span class="highlight">test</span> thanks.</span>
I try this xslt, only can ge the text inside title tag, how can I also convert the highlight tag?
<span class="title"><xsl:value-of select="title"/></span>
<xsl:template match="title">
<span class="title">
<xsl:apply-templates />
</span>
</xsl:template>
<xsl:template match="highlight">
<span class="highlight">
<xsl:apply-templates />
</span>
</xsl:template>
or, if you want, collapse it into a single template:
<xsl:template match="title|highlight">
<span class="{name()}">
<xsl:apply-templates />
</span>
</xsl:template>
Key point is the <xsl:apply-templates /> - it runs all child nodes of the current node through the appropriate templates. In the upper variant, the appropriate templates are separate, in the lower variant the one template is called recursively.
There is a default rule defined in XSLT that copies text nodes. All text is run through this rule by <apply-templates>, so text nodes appear in the output autmatically.
Use xsl:copy-of instead of xsl:value-of if you want a full copy of the node and all of its children:
<span class="title"><xsl:copy-of select="title"/></span>
But for what you are trying to do, I would create one template for the title element and one for the highlight element:
<xsl:template match="title">
<span class="title"><xsl:value-of select="." /></span>
<xsl:apply-templates />
</xsl:template>
<xsl:template match="highlight">
<span class="highlight"><xsl:value-of select="." /></span>
</xsl:template>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" encoding="utf-8" />
<xsl:template match="/">
<html>
<body>
<span>
<div style="background-color:#000066;color:#EEEEEE;padding:7px">
<a name="top" style="padding-left:10px;font-size:28pt">Alerting Variables</a>
</div>
</span>
<div style="display:block;padding-left:50px;padding-bottom:10px" class="hbuttons">
LDMS Alerts
LDSM Alerts
Why?
Examples
Resources
</div>
<div style="clear: left;"></div>
<!-- This is the Table of Contents-->
<div style="padding:5px">
<div style="padding:5px;margin-top:10pt;margin-bottom:10pt;font-weight:bold;font-size:20px">Table of Contents -
<a style="position:absolute;margin-left:40px" href="PrintPages/PrintAll.html">
<img border="0" src="images/PrintButton.png" />
</a></div>
<div style="font-family:Arial;font-weight:bold;margin-left:30px;font-size:10pt">
<xsl:if test="contains(identifiers/sectionname/alert/#name, 'Agent Watcher')">
Agent Watcher
<a style="position:absolute;margin-left:40px" href="PrintPages/PrintAW.html">
<img border="0" src="images/PrintButton.png" />
</a>
</xsl:if>
<ol style="margin-top:5">
<xsl:for-each select="identifiers/sectionname/alert">
<xsl:if test="contains(#name, 'Agent Watcher')">
<li style="margin-left:10pt;font-size:8pt">
<a>
<xsl:attribute name="href">#
<xsl:value-of select="#name" /></xsl:attribute>
<xsl:value-of select="#name" />
</a>
</li>
</xsl:if>
</xsl:for-each>
</ol>
</div>
<div style="font-family:Arial;font-weight:bold;margin-left:30px;font-size:10pt">
Intel vPro
<a style="position:absolute;margin-left:40px" href="PrintPages/PrintvPro.html">
<img border="0" src="images/PrintButton.png" />
</a>
<ol style="margin-top:5">
<xsl:for-each select="identifiers/SectionName/alert">
<xsl:if test="contains(#name, 'Intel vPro')">
<li style="margin-left:10pt;font-size:8pt">
<a>
<xsl:attribute name="href">#
<xsl:value-of select="#name" /></xsl:attribute>
<xsl:value-of select="#name" />
</a>
</li>
</xsl:if>
</xsl:for-each>
</ol>
</div>
</div>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
Above is my code sample.
The first xsl:if statement always fails and never shows the Agent Watcher text or print me button. Even if the section is filled out in the XML. If the section is there, the first xsl:if statement fails, but the second one, contained in the xsl:for-each shows the content. How do I get this to work.
I want to have it encompassing so that if the XML has content in the section it will put it up but if not it wont be empty content with a header or vice versa. Attaching sample XML to process.
<identifiers>
<sectionname>
<alert name="Agent Watcher Service Startup"></alert>
<alert name="Agent Watcher Service Not Started"></alert>
<alert name="Agent Watcher Service Uninstalled"></alert>
<alert name="Agent Watcher File Deleted"></alert>
</sectionname>
<sectionname>
<alert name="Intel vPro agentless discovery failure"></alert>
<alert name="Intel vPro System Defense Remediation Alert"></alert>
<alert name="Intel vPro Enhanced System Defense Remediation Alert"></alert>
<alert name="Intel vPro Enhanced System Defense Alert"></alert>
</sectionname>
</identifiers>
Blockquote
I have a few other suggestions but you need to post the entire (relevant) XSLT before I can go on. At least the enclosing template is necessary.
EDIT: Here is my proposal for your stylesheet:
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:tmp="http://tempuri.org"
exclude-result-prefixes="tmp"
>
<tmp:config>
<tmp:alert label="Agent Watcher" link="PrintPages/PrintAW.html" />
<tmp:alert label="Intel vPro" link="PrintPages/PrintvPro.html" />
</tmp:config>
<xsl:variable name="everyAlert" select="
/identifiers/sectionname/alert
" />
<xsl:template match="/">
<html>
<body>
<!-- 8< snip -->
<div style="...">
<div style="...">
<xsl:text>Table of Contents - </xsl:text>
<a style="..." href="PrintPages/PrintAll.html">
<img border="0" src="images/PrintButton.png" />
</a>
</div>
<xsl:for-each select="document('')/*/tmp:config/tmp:alert">
<xsl:call-template name="section" />
</xsl:for-each>
</div>
</body>
</html>
</xsl:template>
<xsl:template name="section">
<xsl:variable name="this" select="." />
<xsl:variable name="alerts" select="
$everyAlert[contains(#name, $this/#label)]
" />
<xsl:if test="$alerts">
<div style="...">
<a href="#{translate($this/#label, ' ', '_')}">
<xsl:value-of select="$this/#label" />
</a>
<a style="..." href="{$this/#link}">
<img border="0" src="images/PrintButton.png" />
</a>
<ol style="...">
<xsl:for-each select="$alerts">
<li style="...">
<xsl:value-of select="#name" />
</li>
</xsl:for-each>
</ol>
</div>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
Key features:
efficient code reuse through a named template
printed sections are easily configurable
uses <xsl:text> elements to avoid unwanted whitespace in the output while retaining freedom to format the XSLT code properly
uses attribute literal notation (the curly braces {}) instead of verbose <xsl:attribute> elements
uses a temporary namespace to allow storing config data in the stylesheet itself
uses an <xsl:for-each> loop and the document() function to retrieve and work with that config data
the for-each makes use of the context to transport the current #label and #link so no <xsl:param> is necessary (the <xsl:template name="section"> runs in tmp:config/tmp:alert context, not in sectionname/alert context!)
uses a global variable ($everyAlert) to store all nodes for later use
I have a item list and for each item I want to make it an url.
List:
<root>
<tags>
<tag>open source</tag>
<tag>open</tag>
<tag>advertisement</tag>
<tag>ad</tag>
</tags>
</root>
XSLT:
<xsl:template match="*">
<div class="tags">
<xsl:for-each select="/post/tags/tag">
<a href="#">
<xsl:value-of select="//tag"/>
</a>
</xsl:for-each>
</div>
</xsl:template>
Output:
<div class="tags">
open source
open source
open source
open source
</div>
What am I doing wrong?
A more XSLT way of doing the correct thing is add a "tag" template and modify your original:
<xsl:template match="*">
<div class="tags">
<xsl:apply-templates select="tag" />
</div>
</xsl:template>
<xsl:template match="tag">
<a href="#">
<xsl:value-of select="."/>
</a>
</xsl:template>
What you are doing with the value-of expression is selecting all of the tag nodes in the xml document:
<xsl:value-of select="//tag"/>
The effect of that is that only the first selected node will be used for the value.
You can use the following instead:
<xsl:value-of select="."/>
Where select="." will select the current node from the for-each.