Extract image from CDATA-xml rss file into xslt - image

I need show with xslt information about an xml RSS feed.
The xml source is:
<description><![CDATA[<p>
<img style="margin: 10px;
float: left;" alt="Nuevo modelo general de negocio"
src="http://mysite.es/images/figure1.jpg" width="196" height="147" />
La compañía apuesta por un marcado giro en el modelo]]>
</description>
I´m using:
<xsl:value-of select="description" disable-output-escaping="yes"/>
But the rendering is not good because I need show a resize image, with size, for example 70x70.
I´ve tried with this but its wrong:
<xsl:value-of select="replace("description","images/","images/resized/images/")"
disable-output-escaping="yes"/>
The perfect solution for me would be to extract separated, both the src property and the text from the tag.
Regards,
María

If your xml always is like your example then you should be able to use something like this:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
exclude-result-prefixes="xsl">
<xsl:output method="xml" omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/">
<div>
<xsl:apply-templates select="rss/channel"/>
</div>
</xsl:template>
<xsl:template match="rss/channel">
<ul>
<xsl:apply-templates select="item"/>
</ul>
</xsl:template>
<xsl:template match="item">
<xsl:variable name="item_link" select="link"/>
<xsl:variable name="item_title" select="substring-after(description, '/>')"/>
<xsl:variable name="item_image" select="substring-before(substring-after(description, 'src="'), '"')" />
<li>
<a href="{$item_link}">
<img alt="" src="{$item_image}" width="70" height="70" />
<xsl:value-of select="$item_title"/>
</a>
</li>
</xsl:template>
</xsl:stylesheet>

Related

XPath - replace element's name

Sample html:
<div>
<button class="show-more-button" data-url="https://www.example.com/">
View More
</button>
</div>
I need a scraping project to interpret the BUTTON element as A and data-url as href:
<div>
<A class="show-more-button" href="https://www.example.com/">
View More
</button>
</div>
Here is my attempt so far. Tried with bothe replace and tranlate:
//DIV/BUTTON[translate(DIV, "BUTTON", "A")][translate(DIV, "data-url", "href")][contains(#class, "show-more-button")]
How can I achieve it?
Applying an XSLT like this, you can transform the HTML and convert the button into a and #data-url into #href:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes" />
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="button">
<a>
<xsl:apply-templates select="#*|node()"/>
</a>
</xsl:template>
<xsl:template match="#data-url">
<xsl:attribute name="href">
<xsl:value-of select="."/>
</xsl:attribute>
</xsl:template>
</xsl:stylesheet>
If you only want to convert the #data-url of button elements, then adjust the generic match expression #data-url to button/#data-url.

XSLT IF evaluation rules

From the XML file :
<store >
<tools>
<tool IDT="T1">
<container>B1</container>
<container>B2</container>
</tool>
<tool IDT="T2">
<container>B1</container>
</tool>
<tool IDT="T3">
<container>B2</container>
</tool>
</tools>
<boxes>
<box IDB="B1" height="10" width="20" length="30" weight="4"/>
<box IDB="B2" height="5" width="40" length="30" weight="2"/>
</boxes>
</store>
I try to display for each box the list of tools that go into each box. For that, I wrote the following XSL:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:fn="http://www.w3.org/2005/xpath-functions">
<xsl:output
method="html"
encoding="UTF-8"
doctype-public="-//W3C//DTD HTML 4.01//EN"
doctype-system="http://www.w3.org/TR/html4/strict.dtd"
indent="yes" />
<xsl:template match="/">
<html>
<head>
<title>Boxes contents</title>
<link type="text/css" rel="stylesheet" href="styles.css" />
</head>
<body>
<h1>Boxes contents</h1>
<ul>
<xsl:apply-templates select="/store/boxes/box" />
</ul>
</body>
</html>
</xsl:template>
<xsl:template match="box" >
<li><xsl:text>Box </xsl:text>
<xsl:value-of select="#ID"/>
<xsl:text>contains the following tools : </xsl:text>
</li>
<xsl:call-template name="findTools" >
<xsl:with-param name="currentBOX" select="#IDB"/>
</xsl:call-template>
</xsl:template>
<xsl:template name="findTools" >
<xsl:param name="currentBOX" />
<xsl:for-each select="/store/tools/tool/container" >
<xsl:if test="container = $currentBOX" >
<br><xsl:value-of select="#IDT"/></br>
</xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
When I do it, I never see the tools. In debug under OXYGEN, I see that the IF is never true. I do not understand why? I start in XPath and XSLT, thanks for your help
You already are at a <container> element inside the <xsl:for-each>. There are no children, so selecting another <container> inside the <xsl:if> won't return anything.
You mean to execute your check from the <tool> node.
<xsl:for-each select="/store/tools/tool">
<xsl:if test="container = $currentBOX">
<xsl:value-of select="#IDT"/><br />
</xsl:if>
</xsl:for-each>
which is easier written as
<xsl:for-each select="/store/tools/tool[container = $currentBOX]">
<xsl:value-of select="#IDT"/><br />
</xsl:for-each>
Overall a more straight-forward way to write the two templates would be this:
<xsl:template match="box">
<li>
<xsl:text>Box </xsl:text>
<xsl:value-of select="#ID"/>
<xsl:text>contains the following tools : </xsl:text>
</li>
<xsl:apply-templates select="/store/tools/tool[container = current()/#IDB]" />
</xsl:template>
<xsl:template match="tool">
<xsl:value-of select="#IDT"/><br />
</xsl:template>
And alternatively you can use an <xsl:key> to index <tool> elements by their <container> value:
<xsl:key name="kToolByContainer" match="/store/tools/tool" use="container" />
<xsl:template match="box">
<li>
<xsl:text>Box </xsl:text>
<xsl:value-of select="#ID"/>
<xsl:text>contains the following tools : </xsl:text>
</li>
<xsl:apply-templates select="key('kToolByContainer', #IDB)" />
</xsl:template>
<xsl:template match="tool">
<xsl:value-of select="#IDT"/><br />
</xsl:template>

Match URL-Pattern in XSLT 1 Attribute using XPATH

Have this given piece of RDF/XML (can’t change it…):
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:cel="http://namespaces.semaworx.org/content#" xmlns:dct="http://purl.org/dc/terms/" xmlns:i18n21="http://apache.org/cocoon/i18n/2.1">
<cel:page>
<dct:hasPart>
<cel:Element rdf:about="http://resources.semaworx.eu/content/element/start_navigation_home">
<cel:hasStructureI18n rdf:parseType="Literal"><i18n21:translate><i18n21:text key="start_navigation_home">Start</i18n21:text></i18n21:translate></cel:hasStructureI18n>
<i18n21:key>TheI18nKey</i18n21:key>
</cel:Element>
</dct:hasPart>
</cel:page>
</rdf:RDF>
Now I need to XSLT template-match specific "i18n21:key"-Elements based upon the URI in the "cel:Element"’s "rdf:about" attribute.
Best approach this far was something like
"cel:Element[contains(#rdf:about,'element/start_navigation_home')]/i18n21:key"
So this is an excerpt from the XSLT:
<xsl:template match="dct:hasPart" mode="layoutject_navigationMain_top">
<header id="navbar">
<nav>
<xsl:if test="$device != 'phone'">
<xsl:apply-templates select="cel:Element" mode="layoutject_languageSwitch"/>
<xsl:apply-templates select="cel:Element" mode="layoutject_navigationMain_inlineContent"/>
</xsl:if>
</nav>
</header>
</xsl:template>
<xsl:template match="cel:Element" mode="layoutject_navigationMain_inlineContent">
<ul id="main">
<xsl:apply-templates select="cel:Element[contains(#rdf:about,'urbanHOTBED/element/start_navigation_home')]/i18n21:key" mode="layoutject_navigationMain_singleItem" />
</ul>
</xsl:template>
<xsl:template match="cel:Element[contains(#rdf:about,'element/start_navigation_home')]/i18n21:key" mode="layoutject_navigationMain_singleItem">
<li class="ff">
<a href="/" title="back to Homepage" i18n21:attr="href title" class="nav_start">
<xsl:value-of select="cel:Element[contains(#rdf:about,'element/start_navigation_home')]/i18n21:key"/>
</a>
</li>
</xsl:template>
It’s only the last template, which won’t match as hoped for.
This far, I have tried being less specific in the "apply-templates" clause, as well as matching the full URI instead of using "contains".

Finding nested elements with XPath (same type)

I can’t figure out how to find nested elements of the same type. Typically, if I have 7 levels of headers and want to transform them with XSLT to h1–h7 heads, how to choose them with XPath—I can’t make out nothing better than div/div/div/head but this seems really clumsy.
This transformation:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|#*">
<xsl:copy>
<xsl:apply-templates select="node()|#*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="div/head">
<xsl:element name="h{count(ancestor::div)}">
<xsl:apply-templates select="node()|#*"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
when applied on this XML document:
<div>
<head>1</head>
<div>
<head>2-1</head>
<div>
<head>3-1</head>
</div>
</div>
<div>
<head>2-2</head>
</div>
</div>
produces the wanted, correct result:
<div>
<h1>1</h1>
<div>
<h2>2-1</h2>
<div>
<h3>3-1</h3>
</div>
</div>
<div>
<h2>2-2</h2>
</div>
</div>

How to add an image title in XSL?

I would like to add a title below each image. My xsl-file looks like this where I loop through each image:
<Testresult>
<xsl:for-each select="Testresult/image">
<img src="{#href}" width="333px" length="350px"/>
<title><xsl:value-of select="//Type"/></title>
<xsl:attribute name="src">
<xsl:value-of select="Testresult/Image"/>
</xsl:attribute>
</xsl:for-each>
</Testresult>
My xml-file looks like this:
<Testresult>
<image href="c:\image1.png"/>
<image href="c:\image2.png"/>
</Testresult>
The output should look like this:
thanks for the help!
try this stylesheet:
<?xml version="1.0" encoding="utf-8" ?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output indent="yes"/>
<xsl:template match="/">
<Testresult>
<xsl:for-each select="Testresult/image">
<img src="{#href}" width="333px" length="350px"/>
<title><xsl:value-of select="#href"/></title>
</xsl:for-each>
</Testresult>
</xsl:template>
</xsl:stylesheet>

Resources