Match URL-Pattern in XSLT 1 Attribute using XPATH - 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".

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.

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>

Similar type of data not matching the same case

I've the below XML
<?xml version="1.0" encoding="UTF-8"?>
<body>
<para><content-style font-style="bold">1/7 7.</content-style> This is First</para>
<para><content-style font-style="bold">1/8 8.</content-style> This is second<content-style format="superscript">6</content-style></para>
</body>
Here when i'm trying to apply template using my XSLT, though the above 2 paras are of same format, first is working and the second is not.
The expected output is as below.
<div class="para"><a name="P1-7"></a><span class="phrase">1/7</span> 7. This is First
</div>
<div class="para"><a name="P1-8"></a><span class="phrase">1/8</span> 8. This is second <span class="format-superscript">6</span>
</div>
and the current output that i get is
<div class="para"><a name="P1-7"></a><span class="phrase">1/7</span> 7. This is First
</div>
<para><span class="font-style-bold">1/8 8.</span> This is second<span class="format-superscript">6</span></para>
please let me know where am i going wrong and how to fix it.
Below is my XSL
<xsl:template match="para[content-style[matches(., '(\w+)/(\w+)')]][1]">
<div class="para">
<xsl:choose>
<xsl:when test="contains(substring-after(substring-after(./content-style/text(),'/'),'/'),' ')">
<xsl:analyze-string select="substring-before(.,' ')" regex="(\w+)/(\w+)/(\w+)">
<xsl:matching-substring>
<a name="{concat('P',regex-group(1),'-',regex-group(2),'-',regex-group(3))}"/>
<span class="phrase">
<xsl:value-of select="."/>
</span>
</xsl:matching-substring>
<xsl:non-matching-substring>
<xsl:analyze-string select="." regex="(\w+)/(\w+)">
<xsl:matching-substring>
<a name="{concat('P',regex-group(1),'-',regex-group(2))}"/>
<span class="phrase">
<xsl:value-of select="."/>
</span>
<xsl:text>     </xsl:text>
</xsl:matching-substring>
<xsl:non-matching-substring>
<xsl:value-of select="."/>
</xsl:non-matching-substring>
</xsl:analyze-string>
</xsl:non-matching-substring>
</xsl:analyze-string>
<xsl:choose>
<xsl:when test="./#format">
<span class="format-{#format}">
<xsl:value-of select="substring-after(.,' ')"/>
</span>
</xsl:when>
<xsl:otherwise>
<xsl:variable name="fontStyle">
<xsl:value-of select="concat('font-style-',#font-style)"/>
</xsl:variable>
<span class="{$fontStyle}">
<xsl:value-of select="substring-after(.,' ')"/>
</span>
</xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:otherwise>
<xsl:analyze-string select="." regex="(\w+)/(\w+)/(\w+)">
<xsl:matching-substring>
<a name="{concat('P',regex-group(1),'-',regex-group(2),'-',regex-group(3))}"/>
<span class="phrase">
<xsl:value-of select="."/>
</span>
</xsl:matching-substring>
<xsl:non-matching-substring>
<xsl:analyze-string select="." regex="(\w+)/(\w+)">
<xsl:matching-substring>
<a name="{concat('P',regex-group(1),'-',regex-group(2))}"/>
<span class="phrase">
<xsl:value-of select="."/>
</span>
<xsl:text>     </xsl:text>
</xsl:matching-substring>
<xsl:non-matching-substring>
<xsl:value-of select="."/>
</xsl:non-matching-substring>
</xsl:analyze-string>
</xsl:non-matching-substring>
</xsl:analyze-string>
</xsl:otherwise>
</xsl:choose>
</div>
</xsl:template>
<xsl:template match="content-style">
<xsl:apply-templates select="./node()[1][self::page]" mode="first"/>
<xsl:choose>
<xsl:when test="./#format">
<span class="format-{#format}">
<xsl:apply-templates/>
</span>
</xsl:when>
<xsl:otherwise>
<xsl:variable name="fontStyle">
<xsl:value-of select="concat('font-style-',#font-style)"/>
</xsl:variable>
<span class="{$fontStyle}">
<xsl:apply-templates/>
</span>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
Working DEmo
Thanks
If you don't want the first paragraph only, don't request it.
para[content-style[matches(., '(\w+)/(\w+)')]][1]
^
|
here
Remove the quantifier and insert it into another expression as indicated:
contains(substring-after(substring-after(./content-style[1]/text(),'/'),'/'),' ')
^
|
here

XSLt - Select image contains in filename 'img_'

Hello i have a question about XSL . I try to select all images in a directory with starts with filename 'img_'. at the moment my code is this:
<div class="flex-container">
<div class="flexslider">
<ul class="slides">
<xsl:for-each select="entry/fields/*[#type = 'image']">
<img>
<xsl:attribute name="src">
<xsl:value-of select="data/#image"/>
</xsl:attribute>
</img>
</li>
</xsl:for-each>
</ul>
</div>
</div>
what i tried is this
<div class="flex-container">
<div class="flexslider">
<ul class="slides">
<xsl:for-each select="entry/fields/*[#type = 'image' contains( ., 'img_' )]">
<li>
<img>
<xsl:attribute name="src">
<xsl:value-of select="data/#image"/>
</xsl:attribute>
</img>
</li>
</xsl:for-each>
</ul>
</div>
</div>
Can anyone help?
I hope its the right form to ask here .
Greetings
It seems, you just want to filter those images which are present, without breaking any link. So, you should use java extension to make it happen because XSLT only is not sufficient. Use something like:
<xsl:template match=file">
<xsl:variable name="file" select="resolve-uri(#name, base-uri(.))"
as="xs:string"/>
<xsl:if test="not(file:exists(file:new($file)))">
<xsl:value-of select="#name"/><xsl:message>file missing /
incorrect name</xsl:message>
</xsl:if>
</xsl:template>
I may get further information from http://www.altova.com/list/xsl-list/200906/msg1000300010.html

Extract image from CDATA-xml rss file into xslt

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>

Resources