I want to flatten an XML document such that every element would copy the attributes of its parent and convert <span/> into <text/>
Input:
<el value="
<span bold="true">
one
<span italics="true">
two
<span superscript="true">
three
</span>
</span>
</span>
<span subscript="true">
four
</span>
"/>
Output:
<text bold="true">one</text>
<text bold="true" italics="true">two</text>
<text bold="true" italics="true" superscript="true">three</text>
<text subscript="true">four</text>
I've tried using copy-of with .. but that obviously only copies one level up from the input. I presume I need a variable but I am unsure of how to operate on it - it doesn't seem like I can do <xsl:value-of select="$text-element"><!--call template--></xsl:value-of>. The fact that this is a string inside an attribute doesn't help either...
Something like this might help, once you make the XML well-formed:
<xsl:template match="text()">
<text>
<xsl:copy-of select="ancestor::*/#*"/>
<xsl:value-of select="normalize-space()"/>
</text>
</xsl:template>
Related
I need to find a specific text value within a document,'method'and for each instance replace that text value 'method' with the following:
element to replace method
This 'method' value can appear several times throughout the document. The issue is that I also need to retain the remaining text within the element, apart from 'method' which will be replaced.
<section id="1">
<title>Methods</title>
<p>The test method blah has 6 types of methods available</p>
<p>With the exception of a specific method<p
</section>
<section id="2">
<title>Organisations</title>
<p>The organisation has a method</p>
</section>
I'm not sure if using fn:replace would the best approach, and if i also need to use regular expressions (something i'm not currently familiar with). Any advice on an approach here would be greatly appreciated.
Expected output only replaces the exact text 'method' with the content element, but retains 'methods':
<section id="1">
<title>Methods</title>
<p>The test <content type="description" xlink:href="linktodescription">method</named-content> blah has 6 types of methods available</p>
</section>
<section id="2">
<title>Organisations</title>
<p>The organisation has a <content type="description" xlink:href="linktodescription">method</named-content></p>
</section>
Assuming Saxon 9 as the XSLT processor you can use (based on http://saxonica.com/html/documentation/xsl-elements/analyze-string.html)
<xsl:template match="section/p">
<xsl:copy>
<xsl:analyze-string select="." regex="\bmethod\b" flags=";j">
<xsl:matching-substring>
<content type="description" xlink:href="linktodescription">
<xsl:value-of select="."/>
</content>
</xsl:matching-substring>
<xsl:non-matching-substring>
<xsl:value-of select="."/>
</xsl:non-matching-substring>
</xsl:analyze-string>
</xsl:copy>
</xsl:template>
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>
I have a Section in a result from and XSLT file that is like this:
<dl class="price-list">
<dt> </dt>
<dd class="salesprice">
DKK <span class="pricethousands">2</span>
<span class="pricegroupingseparator">.</span>
<span class="pricehundreds">714</span>
<span class="pricedecimalseparator">,</span><span class="pricedecimals">40</span>
</dd>
</dl>
I have tried a few times to change the XSLT but i do not seem to be able to change it.
I'd like the result to become something like this or similar:
<div>
<p>DKK </p>
<p>2.714,40</p>
</div>
the xslt is currently using something like this:
<xsl:template match="/">
<xsl:variable name="html">
<xsl:for-each select="msxml:node-set($list)/product">
<xsl:call-template name="list-product">
<xsl:with-param name="list-product" select="."/>
<xsl:with-param name="list-vat" select="$list-vat"/>
....
</xsl:call-template>
</xsl:for-each>
</xsl:variable>
<xsl:copy-of select="$html" />
</xsl:template>
I hope you can help me to make this work. I know I haven't provided it all but as it is currently I can't provide more because I'm not allowed to.
<product>
<estocklevel></estocklevel>
<variantof></variantof>
<id></id>
<weightingram>137750</weightingram>
<unit></unit>
<volume>0</volume>
<discountgroup></discountgroup>
<manufactor></manufactor>
<deliverydate></deliverydate>
<url></url>
<texts></texts>
<name></name>
<longdescription></longdescription>
<shortdescription></shortdescription>
<htmltitle></htmltitle>
<metadescription></metadescription>
<metakeywords></metakeywords>
<group></group>
<alternativeitemid></alternativeitemid>
<alternativeitemrule></alternativeitemrule>
<duties></duties>
<priceinfo currency="" price="" standardsalesprice="" vatincludedinprice="False" vatrate="" quantity="">
<incvat price="">
<price></price>
<standardsalesprice></standardsalesprice>
<discountamount></discountamount>
<discountpercentage></discountpercentage>
<vat></vat>
</incvat>
<exvat price="">
<price></price>
<standardsalesprice></standardsalesprice>
<discountamount></discountamount>
<discountpercentage></discountpercentage>
<vat></vat>
</exvat>
</priceinfo>
<bulkdiscountpricelist></bulkdiscountpricelist>
<productcategories extra="productcategories"></productcategories>
<indicativedate extra="indicativedate"></indicativedate>
<oncampaign extra="oncampaign"></oncampaign>
<cnt extra="cnt"></cnt>
<weight extra="weight"></weight>
<misc extra="misc"></misc>
<dcurlv2 extra="dcurlv2"></dcurlv2>
Source:
<txt>
<Data>
<div class="label">
<span>Welcome</span>
<span id="UserName"></span>.
</div>
</Data>
</txt>
Output required:
<Data>
<div class="label">
<span>Welcome</span>
<span id="UserName"></span>.
</div>
</Data>
Rule:
I want to replace
< with <
> with >
There are other characters also, for simplicity I have mentioned two only.
I am not sure how to search for a string in xslt and replace it.
You could achieve this by using disable-output-escaping
<xsl:template match="txt">
<xsl:value-of select="." disable-output-escaping="yes" />
</xsl:template>
That should give you the output you require.
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>