My input is having URL, this needs to come in both attribute value and content value in the output using XSL:
My Input xml is:
<link>
<Url>http://tneb.gov/</Url>
</link>
XSL I Used as:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="Url">
<xsl:element name="xref">
<xsl:attribute name="format">
<xsl:text>html</xsl:text>
</xsl:attribute>
<xsl:attribute name="href">
<xsl:value-of select="ancestor-or-self::link/Url"/>
</xsl:attribute>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
Output I get as:
<xref format="html" href="http://tneb.gov/"/>
But i need as:
<xref format="html" href="http://tneb.gov/">http://tneb.gov/</xref>
Please give me suggestion on this. Thanks in advance
Why don't you do simply:
<xsl:template match="Url">
<xref format="html" href="{.}">
<xsl:value-of select="."/>
</xref>
</xsl:template>
Notes:
It's not necessary to use xsl:element if the name of the element is
known - see: https://www.w3.org/TR/xslt20/#literal-result-element
Learn about attribute value templates:
https://www.w3.org/TR/xslt20/#attribute-value-templates
Learn about the context item expression:
https://www.w3.org/TR/xpath20/#id-context-item-expression
Related
My source XML:-
<wireframe:xaIDExclusion>
<widget:xaID id="12"/>
<widget:xaID id="121"/>
<widget:xaID id="123"/>
<widget:xaID id="124"/>
<widget:xaID id="3456"/>
</wireframe:xaIDExclusion>
This is what i tried
<xsl:template match="widget:xaID">
<xsl:element name="xaid">
<xsl:variable name ="value" select="#id"></xsl:variable>
<xsl:value-of select="concat($value,',')"></xsl:value-of>
</xsl:element>
</xsl:template>
I need output like this,how to do that
12,121,123,124,3456
Thanks in advance
The problem with your approach is that you're matching widget:xaID and then creating a xaid element; this results in multiple xaid elements, one for each widget:xaID. You need to create the xaid element while you are in the context of the parent of widget:xaID.
Try (untested, because you did not provide a well-formed XML):
<xsl:template match="wireframe:xaIDExclusion">
<xaid>
<xsl:for-each select="widget:xaID">
<xsl:value-of select="#id">
<xsl:if test="position()!=last()">, </xsl:if>
</xsl:for-each>
</xaid>
</xsl:template>
I am having the following code on my full length XSLT, and, its creates some errors during transformation.
The error is XPTY0004: A sequence of more than one item is not allowed as the first argument of matches()
<xsl:template match="par[#class='tablecaption']" exclude-result-prefixes="html">
<p class="caption1">
<xsl:variable name="n2" select="./text()|./*/text()"/>
<xsl:attribute name="id">
<xsl:if test="matches($n2, '(Table)\s(\d+|[A-Z])(\.)(\d+)')">
<xsl:variable name="y2" select="replace($n2, '(Table)\s(\d+|[A-Z])(\.)(\d+)', '$4')"/>Tab<xsl:value-of select="normalize-space(substring($y2, 1, 2))"/></xsl:if>
</xsl:attribute>
<strong><xsl:apply-templates/></strong></p>
</xsl:template>
What is the wrong here? pls
Change your variable n2 to ./descendant::text()[1]
<xsl:template match="par[#class='tablecaption']" exclude-result-prefixes="html">
<p class="caption1">
<xsl:variable name="n2" select="./descendant::text()[1]"/>
<xsl:attribute name="id">
<xsl:if test="matches($n2, '(Table)\s(\d+|[A-Z])(\.)(\d+)')">
<xsl:variable name="y2" select="replace($n2, '(Table)\s(\d+|[A-Z])(\.)(\d+)', '$4')"/>Tab<xsl:value-of select="normalize-space(substring($y2, 1, 2))"/></xsl:if>
</xsl:attribute>
<strong><xsl:apply-templates/></strong></p>
</xsl:template>
with this input
<root>
<par class="tablecaption"> Table A.1 <bold>text2</bold></par>
</root>
it gets:
<root>
<p class="caption1" id="Tab1"><strong> Table A.1 <bold>text2</bold></strong></p>
</root>
Im using doctype: XHTML Mobile Profile 1.2, XML version="1.0 and Content-Type "application/xhtml+xml"
Is it possible to disable or prevent <cite> tag appearing within RSS feed, Due to the fact that I keep getting this error on the Page itself.
error on line 24 at column 70: expected '>'
Below is a rendering of the page up to the first error.
I am using an external feed from another site, which is not mine to control or edit.
I am using an XSLT and ColdFusion file to read the external RSS file, and display it the way I want within my XSLT, I already have in place disable-output-escaping="yes" to prevent lose code showing up within the feed. My XSLT works when this tag is not there
I have tried to get around it, but no luck. Is it actually possible to do this?
CFM
<cfcontent type="application/xhtml+xml" reset="yes">
<!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.2//EN" "http://www.openmobilealliance.org/tech/DTD/xhtml-mobile12.dtd">
<cfhttp method="Get" url="http://www.animenewsnetwork.com/news/rss.xml">
<cfset xmlInput = CFHTTP.FileContent>
<cfset MyXslFile = Expandpath("animenewsrss.xsl")>
<cffile action="READ" variable="xslInput" file="#MyXslFile#">
<cfset xmlOutput = XMLTransform(xmlInput, xslInput)>
<cfoutput>#xmloutput#</cfoutput>
XSLT
<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" omit-xml-declaration="yes" />
<xsl:template match="rss/channel">
<xsl:element name="html">
<xsl:element name="head">
<xsl:element name="title">Anime News</xsl:element>
</xsl:element>
<xsl:element name="body">
<xsl:element name="div"><xsl:attribute name="id"><xsl:value-of select="'hstyle'"/></xsl:attribute>Media Events UK - Anime News</xsl:element>
<xsl:element name="div"><xsl:attribute name="id"><xsl:value-of select="'nstyle'"/>
</xsl:attribute><xsl:element name="a"><xsl:attribute name="href">index.cfm</xsl:attribute>Home</xsl:element> -
<xsl:element name="a"><xsl:attribute name="href">listings.cfm</xsl:attribute>Listings</xsl:element> -
<xsl:element name="a"><xsl:attribute name="href">venue.cfm</xsl:attribute>Venues</xsl:element>
</xsl:element>
<xsl:apply-templates select="item[position() < 6]" />
</xsl:element>
</xsl:element>
</xsl:template>
<xsl:template match="item[position() < 6]">
<div class="rsstyle">
<xsl:element name="a">
<xsl:attribute name="href">
<xsl:value-of select="link"/>
</xsl:attribute>
<xsl:value-of select="title" />
</xsl:element>
<xsl:element name="div">
<xsl:value-of select="pubDate" />
</xsl:element>
<xsl:element name="div">
<xsl:value-of select="concat(substring(description, 1, 50), '...')" disable-output-escaping="yes"/>
</xsl:element>
</div>
</xsl:template>
</xsl:stylesheet>
With this line
<xsl:value-of select="concat(substring(description, 1, 50), '...')" disable-output-escaping="yes"/>
you cut the content of <description>, which contains cite elements in some cases. This leads to lines like the following in your result HTML:
<div><cite>Ni No Kuni</cite>, <cite>Tales of Xillia</ci...</div>
As you can see, the cite element is not closed properly anymore, because you cut the content of the description element at 50 characters. If you counted the characters, you'd notice that the content of description stops at 50, then "..." is inserted.
If you describe your intent behind applying substring to decription elements, SO can help you find a good alternative to this.
My guess is that you need to take into account the possibility that description contains not only text, but also elements (like cite). Then, it makes sense to use substring only on the text content of description, like this:
concat(substring(description/text(),1,50),'...')
Then go on to catch the child elements of description, e.g. in a separate template:
<xsl:template match="cite[parent::description]">
<!--Deal with cite elements-->
</xsl:template>
EDIT: I adapted your stylesheet to process cite elements as children of description. There are 2 additional templates that process text nodes and cite nodes, both being children of description.
<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" omit-xml-declaration="yes" />
<xsl:template match="rss/channel">
<!--I left this template unchanged!-->
</xsl:template>
<xsl:template match="item[position() < 6]">
<div class="rsstyle">
<xsl:element name="a">
<xsl:attribute name="href">
<xsl:value-of select="link"/>
</xsl:attribute>
<xsl:value-of select="title" />
</xsl:element>
<xsl:element name="div">
<xsl:value-of select="pubDate" />
</xsl:element>
<xsl:element name="div">
<xsl:apply-templates select="description"/>
</xsl:element>
</div>
</xsl:template>
<xsl:template match="description">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="text()[parent::description]">
<xsl:copy/>
</xsl:template>
<xsl:template match="cite[parent::description]">
<xsl:value-of select="."/>
</xsl:template>
</xsl:stylesheet>
If have a big 'xsl:choose' chunk in which I need to set a number of defined sets of attributes on different elements.
I really do not like to repeat the definition of sets of attributes inside every branch of the 'choose'.
So I would like to work with a variable that contains those attributes.
A lot easier to maintain and less room for error...
So far I have not been able to call the attribute node out?
I thought they are just a node-set, so copy-of would do the trick.
But that gives me nothing on output.
Is this because attribute nodes are not really children?
But XSLT 1.O does not allow me to address them directly...<xsl:copy-of select="$attributes_body/#*/> returns an error
Here is the stylesheet fragment (reduced from original)
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="list">
<xsl:for-each select="figure">
<xsl:variable name="attributes_body">
<xsl:attribute name="chapter"><xsl:value-of select="#chapter"/></xsl:attribute>
<xsl:attribute name="id"><xsl:value-of select="#id"/></xsl:attribute>
</xsl:variable>
<xsl:variable name="attributes_other">
<xsl:attribute name="chapter"><xsl:value-of select="#book"/></xsl:attribute>
<xsl:attribute name="id"><xsl:value-of select="#id"/></xsl:attribute>
</xsl:variable>
<xsl:choose>
<xsl:when test="ancestor::body">
<xsl:element name="entry">
<xsl:copy-of select="$attributes_body"/>
<xsl:text>Body fig</xsl:text>
</xsl:element>
</xsl:when>
<xsl:otherwise>
<xsl:element name="entry">
<xsl:copy-of select="$attributes_other"/>
<xsl:text>other fig</xsl:text>
</xsl:element>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:template>
If this can not be done in XLST 1.0 would 2.0 be able to do this?
<xsl:variable name="attributes_body">
<xsl:attribute name="chapter"><xsl:value-of select="#chapter"/></xsl:attribute>
<xsl:attribute name="id"><xsl:value-of select="#id"/></xsl:attribute>
</xsl:variable>
You need to select the wanted attributes -- not to copy their contents in the body of the variable.
Remember: Whenever possible, try always to specify an XPath expression in the select attribute of xsl:variable -- avoid copying content in its body.
Solution:
Just use:
<xsl:variable name="attributes_body" select="#chapter | #id">
Here is a complete example:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="x/a">
<xsl:variable name="vAttribs" select="#m | #n"/>
<newEntry>
<xsl:copy-of select="$vAttribs"/>
<xsl:value-of select="."/>
</newEntry>
</xsl:template>
</xsl:stylesheet>
when applied on this:
<x>
<a m="1" n="2" p="3">zzz</a>
</x>
produces:
<newEntry m="1" n="2">zzz</newEntry>
in my case, I was trying to store a tag attribute into a variable
to do so, use this syntax tag-name/#attribute-inside-tag-name
here is an example
<xsl:variable name="articleLanguage" select="/article/#language"/><!--the tricky part -->
//<!--now you can use this this varialbe as you like -->
<xsl:apply-templates select="front/article-meta/kwd-group[#language=$articleLanguage]"/>
and the xml was
<article article-type="research-article" language="es" explicit-lang="es" dtd-version="1.0">
.....
hope this help you
I cant really formulate that better, so I'll go with an example instead:
XML:
<root>
<foo>
<bar id="1">sdf</bar>
<bar id="2">sdooo</bar
</foo>
<feng>
<heppa id="4">hihi</heppa>
<heppa id="2">sseeapeea</heppa>
<heppa id="1">....</heppa>
</feng>
</root>
XSLT:
<xsl:for-each select="/root/foo/bar">
<p>
<xsl:value-of select="." />: <xsl:value-of select="/root/feng/heppa[#id = #id]" />
</p>
</xsl:for-each>
Desired output:
<p>sdf: ....</p>
<p>sdooo: sseeapeea</p>
Actual output:
<p>sdf: hihi</p>
<p>sdooo: hihi</p>
For selecting nodes with XPath 1.0 only, you need to do a node set comparison:
/root/feng/heppa[#id=/root/foo/bar/#id]
Of course, this has NxM complexity (as the others XSLT solutions)
With XSLT 1.0 you should use keys because there are cross references:
<xsl:key name="kBarById" select="bar" use="#id"/>
<xsl:template match="/root/feng/heppa[key('kBarById',#id)]">
<p>
<xsl:value-of select="concat(key('kBarById',#id),': ',.)"/>
</p>
</xsl:template>
I assume you mean /root/foo/bar since /root/foo elements don't have id.
You're comparing the #id with itself, so of course it's true for the first node examined. You can use current() to reference the current node in an expression:
<xsl:for-each select="/root/foo/bar">
<p>
<xsl:value-of select="." />: <xsl:value-of select="/root/feng/heppa[#id = current()/#id]" />
</p>
</xsl:for-each>
Another solution is to read the id attribute into a variable.
<xsl:for-each select="/root/foo/bar">
<xsl:variable name="id" select="#id"/>
<p>
<xsl:value-of select="." />: <xsl:value-of select="/root/feng/heppa[#id = $id]" />
</p>
</xsl:for-each>
This might be handier, if your real use case is more complicated and you need to use the value of the id multiple times in this for-each section.