I have a RSS XML news file, which contains a list of items inclusive of a URL to an image. I also have an associated XSLT.
The problem is that the image sizes are not consistent and I want to limit the image sizes, resize them, to a nice thumbnail.
How would I modify the XSLT to accomplish that?
XML Sample:
<?xml version="1.0" encoding="UTF-8" ?>
<rss version ="2.0" xmlns:g="http://base.google.com/ns/1.0">
<channel>
<title>Company Name</title>
<description>Company description</description>
<link>http://www.mycompanyurl.com</link>
<item>
<title>News Item Title</title>
<link>http://www.whateverurl.com/</link>
<category>Space</category>
<pubDate>12 April 1961</pubDate>
<description>Software to reduce your job search to a half hour per day. all major job sites, job boards, classifieds. unemployment paperwork, CRM, interviews, more</description>
<image>
<url>~/App_Data/NewsControl/whatever.png</url>
<title>Whatever1</title>
<link>javascript:void(0)</link>
</image>
<g:id>1</g:id>
<g:brand>Whatever2</g:brand>
<g:condition>whatever3</g:condition>
<g:price>$whatever4</g:price>
<g:product_type>Whatever5</g:product_type>
</item>
</channel>
</rss>
Here is the associated XSLT:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<items>
<xsl:for-each select="//item">
<item Name="{position()}" HeaderText="{title}" Text="{description}" NavigateUrl="{position()}" Date="{pubDate}" ImageUrl="{image/url}"/>
</xsl:for-each>
</items>
</xsl:template>
</xsl:stylesheet>
Results of First Answer:
<items>
<xsl:for-each select="//item">
<item Name="{position()}" HeaderText="{title}" Text="{description}" NavigateUrl="{position()}" Date="{pubDate}" ImageUrl="/Tools/thumber.php?img={image/url}"/>
</xsl:for-each>
</items>
I made these changes, enabled PHP on the server (testing on from the server and locally), and saw 2 issues:
1. I get no image, merely a no image box.
If I try to edit the ImageUrl and tack on a "&W=xxx&H=xxx", the Visual Studio validator complains and throws up errors on the &.
Update 2
Here is the latest line in the XSLT:
http://myserver.com/Tools/thumber.php?img=',image/url)}"/>
The corresponding image section in the XML
<image>
<url>/Products/Jobfish/Images/Boxshots/Jobfish_DVDCaseCD_ShadowOut.jpg</url>
<title>Jobfish</title>
<link>javascript:void(0)</link>
XSLT has no built in function for resizing or thumbnailing. You will have to use an external processor for that eg. by using a PHP thumbnail generator.
Then replace the original image path with a URL pointing to your thumbnail generator, with the source being the original image.
suppose ImageUrl = mediaserver.xyz/ourlogo.jpg
the new ImageUrl would become myserver.com/thumbnailgenerator.php?src=http://mediaserver.xyz/ourlogo.jpg
Please make shure you select a caching thumbnail library (eg https://code.google.com/p/phpthumbmaker/wiki/ThumberWiki ) , since it will be a serious resource hog if you skip that. Also take into account copyright issues when re-serving these thumbnails.
Related
I'm pretty new to XSLT and I've been struggling to replicate the solution mentioned here
XSL for-each: how to detect last node?
for longer than I'm willing to admit :(
I've setup this fiddle. https://xsltfiddle.liberty-development.net/naZXVFi
I was hoping I could use just the value-of + separator, vs choose / when xslt tools, as it did seem more idiomatic.
I can't get the separator to show up;
nor can I select just the child of skill, I always get the descendants too. That's to say, I shouldn't see any detail in the output.
bonus: not sure why that meta tag is not self closing (warning in the html section)
Desired output:
skill1, skill2, skill3, skill4, skill5 (no comma space for the last one)
Any help would be greatly appreciated. Thanks.
EDIT: including the code here too:
xml: (need to add ref to xslt):
<?xml version="1.0" encoding="utf-8" ?>
<?xml-stylesheet type="text/xsl" href="test.xsl"?> <!-- not in fiddle -->
<skills>
<skill>skill1</skill>
<skill>skill2</skill>
<skill>skill3
<details>
<detail>detail1</detail>
<detail>detail2</detail>
</details>
</skill>
<skill>skill4</skill>
<skill>skill5</skill>
</skills>
And test.xsl:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:math="http://www.w3.org/2005/xpath-functions/math"
xmlns:map="http://www.w3.org/2005/xpath-functions/map"
xmlns:array="http://www.w3.org/2005/xpath-functions/array"
exclude-result-prefixes="#all"
version="3.0">
<xsl:mode on-no-match="shallow-copy"/>
<xsl:output method="html" indent="yes" html-version="5"/>
<xsl:template match="/">
<html>
<head>
<title>.NET XSLT Fiddle Example</title>
</head>
<body>
<xsl:for-each select="/skills/skill">
<xsl:value-of select="." separator=", "/>
</xsl:for-each>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
In general, with XSLT 2/3 to output a sequence separated by some separator string, you simply use xsl:value-of select="$sequence" with the appropriate separator string in the separator attribute (and no for-each):
<xsl:template match="skills">
<xsl:value-of select="skill/text()[normalize-space()]/normalize-space()" separator=", "/>
</xsl:template>
https://xsltfiddle.liberty-development.net/naZXVFi/1
In most cases you would just need select="skill" separator=", " but given your descendants and the white space you seem to want to eliminate the select expression above is a bit more complicated.
Martin has given you the detailed work-through to get the final result including getting rid of the extra spaces etc, but at a high level, here's how to use xsl:value-of with separator correctly.
You have:
<body>
<xsl:for-each select="/skills/skill">
<xsl:value-of select="." separator=", "/>
</xsl:for-each>
</body>
This says that for each skill node, take the content of that node and display it. Notably, the value-of only sees one skill at a time, so there is nothing to join with the comma separator.
The answer which would get you what you want is:
<body>
<xsl:value-of select="/skills/skill" separator=", "/>
</body>
This says to take the set of skill nodes and display them joined by comma separators. You can see the output at https://xsltfiddle.liberty-development.net/naZXVFi/4
How do I grab the contents of an href if it includes a specific word, example:
click here
How do I grab 'contacts.asp' based on that it has the word 'contact' in it?
tried variations of //a/#href[contains(#href,'contact')] but don't seem to be getting anywhere
tried variations of //a/#href[contains(#href,'contact')] but don't seem to be getting anywhere
You are nearly there.
In the contains test, you are already in the context of the href attribute, so your test should be against . rather than the #href your xpath has, which is attempting to look for a href attribute under the href attribute. This of course won't work.
Try
//a/#href[contains(.,'contact')]
This says "find all href attributes on a elements, such that the href attribute value itself contains contact".
Note that this returns the href attribute; the library you're usnig will then have a way to pick out the value.
In your Path you are below #href, so your contains won't work.
Try it like this:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" omit-xml-declaration="yes" indent="yes" version="1.0" encoding="utf-8"/>
<xsl:template match="/">
<xsl:value-of select="//a[contains(#href,'contact')]"/>
</xsl:template>
</xsl:stylesheet>
This StackOverflow answer suggests that you should use HTML entry content and use a standard <img> tag to link to your images.
<content type="html">
<![CDATA[
<a href="http://test.lvh.me:3000/listings/341-test-pics?locale=en">
<img alt="test_pic" src="http://test.lvh.me:3000/system/images/20/medium/test_pic.jpg?1343246102" />
</a>
]]>
</content>
I have also found something called the Yahoo media extensions here which allows you to add custom additional elements.
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/">
<!-- ommitted -->
<entry>
<!-- ommitted -->
<media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="path_to_image.jpg" />
</entry>
</feed>
Google also seems to have its own similar extensions. See here.
<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:g="http://base.google.com/ns/1.0">
<!-- ommitted -->
<entry>
<!-- ommitted -->
<g:image_link>http://www.google.com/images/google_sm.gif</g:image_link>
</entry>
</feed>
My own intuition tells me I should simply be able to add links to images like so:
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<!-- ommitted -->
<entry>
<!-- ommitted -->
<link rel="enclosure" type="image/png" length="1337"
href="http://example.org/image.png"/>
</entry>
</feed>
What is the correct approach for maximum compatibility?
The best practice is to do what Wordpress RSS 2.0 feeds do — if you want your post image to appear in feedly for example, put the <p><img...></p> at the top of the content. My eleventy setup has post header image inside article, but outside content variable's contents which are used in the feed. I solve the problem adding the image back:
<item>
...
<content:encoded>
<![CDATA[<p>{% include "src/components/partials/post-hero-img.njk" %}</p>{{ post.templateContent | textDeletePresentationDivs | htmlToAbsoluteUrls(absolutePostUrl) | safe }}]]>
</content:encoded>
source in git
I checked, neither Atom nor RSS 2.0 feeds have post images set anywhere as standalone tags. They're simply at the top of the article's content.
With regards to your examples...
The "vanilla" Atom RSS feed has a schema xmlns="http://www.w3.org/2005/Atom" and its documentation is defined in RFC4287.
According to it, "vanilla" Atom RSS feed strictly can have <logo> which is the 2:1 ratio image, the logo of the feed. Sadly, it is placed in the root of XML (notice atom:logo in the spec, it's not atom:entry:logo). Practically, this means, you can put a picture of your RSS feed itself, but not per-article. If you do put <logo> inside <entry>, the feed won't pass the validators and post image won't appear in feedly (I tried).
Also, spec defines <icon> which is vaguely defined as a small, square image, also placed in the root. Feedly seem to detect the website's favicon anyway, although it doesn't hurt to set this tag up in rss explicitly.
That's all there is — Atom spec doesn't officially define a way how to put images per-article.
Here's where additional namespaces come in (or RSS 2.0, different spec, different XML). You mentioned xmlns:media="http://search.yahoo.com/mrss/" in example. I tried it, post images won't show in feedly. Plus, spec link http://search.yahoo.com/mrss/ is not showing any specs.
Google namespace you quoted, xmlns:g="http://base.google.com/ns/1.0" also doesn't work, post images don't show up in feedly.
The link approach, <link rel="enclosure" type="image/png" length="1337" href="http://example.org/image.png"/> would be promising except length is meant to state the filesize in bytes. In Eleventy that's problematic value to get, for example.
To sum up, the best practice is put post header image at the top of the content, inside <content>.
I'm using the Kaltura KMC to generate a Yahoo! MRSS feed (per the info here).
The feed it creates looks like this:
<rss version="2.0" xmlns:media="http://search.yahoo.com/mrss/" xmlns:dcterms="http://purl.org/dc/terms/">
<channel>
<title>yahoo mrss feed</title>
<link>http://xxxx.com</link>
<description></description>
<item>
<title>My Dog Clip</title>
<link>http://xxxx.com?videoid=0_udwmgjec</link>
<media:content url="http://xxxx.com/p/100/sp/10000/serveFlavor/flavorId/0_e5h0z4cf">
<media:title>My Dog Clip</media:title>
<media:description>Here is a clip of the dog playing!</media:description>
<media:keywords>dog clip</media:keywords>
<media:thumbnail url="http://xxxx.com/p/100/sp/10000/thumbnail/entry_id/0_udwmgjec/version/100002"></media:thumbnail>
<media:category scheme="http://search.yahoo.com/mrss/category_schema">Entertainment & TV</media:category>
<media:player url="http://xxxx.com/kwidget/wid/_100/entry_id/0_udwmgjec/ui_conf_id/48501"></media:player>
<media:rating scheme="urn:simple"></media:rating>
</media:content>
</item>
</channel>
</rss>
This is pretty good, but I see two things that need adjusting:
On the <media:content> tag, I'd like to add the type parameter, indicating the MIME type. Is there a way to do this through the KMC interface?
I'd like to change the default size of the thumbnail it generates (and also add the image suffix, like .jpg, to the end of the URL). Is there an option for that in the KMC?
It seems like I might end up needing to use the API to build the MRSS feed myself on the fly (pulling the video data from Kaltura via the API). What do you think?
Thank you...
You can use the dynamic MRSS
To upload your owned XSD, and modify the original.
I need help with my problem over here or at least some advice. I am parsing a HTML document using a HTMLcleaner with the use of XPATH.
I have something like this:
<html>
[code and other <h4> tags]
<h4>Random name</h4>
Text I want to get
Text I want to get 2
Text I want to get 3
Text I want to get 4
<h4> Random name 2 </h4>
Text I don't want to get
[code and other <h4> tags]
</html>
Ok. I have several <h4> tags, each one of them with <a> tags and with the some text. My problem is that I don't know how to get all the respective the text from a specific , just like a "h4[i]". I tried something like this but it didn't work:
String xpath = "h4["+number+"]//a" //where number will increment
Thank you in advice for you help!
Use:
/*/h4[1]/following-sibling::a[not(preceding-sibling::h4[2])]/text()
XSLT - based verification:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/">
<xsl:copy-of select=
"/*/h4[1]/following-sibling::a[not(preceding-sibling::h4[2])]/text()"/>
</xsl:template>
</xsl:stylesheet>
When this transformation is applied on the following XML document (the provided fragment, wrapped in a single top element to become an well-formed XML document):
<html>
<h4>Random name</h4>
Text I want to get
Text I want to get 2
Text I want to get 3
Text I want to get 4
<h4> Random name 2 </h4>
Text I don't want to get
</html>
The Xpath expression is evaluated and all selected (text) nodes are copied to the output:
Text I want to get Text I want to get 2 Text I want to get 3 Text I want to get 4