XSLT: get relative URI instead of absolute uri - xslt

I want to:
Create a file in the same folder where I am running my XSLT stylesheet against.
This new file has a list of href to files with a certain value in the copyrholder element.
Have a relative path in the href.
This is what I currently have:
I create a new topic in the same folder
List of href with absolute uri
Problem: make the absolute path relative to file I just created.
Example
This is the folder I am referencing to and all files have that particular element I want in the list:
C:/dita/file1.dita
C:/dita/file2.dita
C:/dita/file3.dita
C:/dita/file4.dita
C:/dita/en/file5.dita
This is the XSLT I use
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="2.0">
<xsl:template match="/">
<xsl:result-document href="newtopic.dita" doctype-public="-//OASIS//DTD DITA Topic//EN" doctype-system="topic.dtd" indent="yes">
<topic id="to_new_topics">
<xsl:element name="title">New topics</xsl:element>
<xsl:element name="body">
<xsl:variable name="folderURI" select="resolve-uri('.',base-uri())"/>
<ul>
<xsl:for-each select="collection(concat($folderURI, '?select=*.dita;recurse=yes'))//copyrholder[contains(., 'value')]">
<li>
<xsl:element name="xref">
<xsl:attribute name="href">
<xsl:value-of select="base-uri()" />
</xsl:attribute>
</xsl:element>
</li>
</xsl:for-each>
</ul>
</xsl:element>
</topic>
</xsl:result-document>
</xsl:template>
</xsl:stylesheet>
This is the current result:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE topic
PUBLIC "-//OASIS//DTD DITA Topic//EN" "topic.dtd">
<topic id="to_new_topics">
<title>New topics</title>
<body>
<ul>
<li><xref href="file:/C:/´dita/file1.dita"/></li>
<li><xref href="file:/C:/´dita/file2.dita"/></li>
<li><xref href="file:/C:/´dita/file3.dita"/></li>
<li><xref href="file:/C:/´dita/file4.dita"/></li>
<li><xref href="file:/C:/dita/en/file5.dita"/></li>
</ul>
</body>
</topic>
This what I would like to have:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE topic
PUBLIC "-//OASIS//DTD DITA Topic//EN" "topic.dtd">
<topic id="to_new_topics">
<title>New topics</title>
<body>
<ul>
<li><xref href="file1.dita"/></li>
<li><xref href="file2.dita"/></li>
<li><xref href="file3.dita"/></li>
<li><xref href="file4.dita"/></li>
<li><xref href="en/file5.dita"/></li>
</ul>
</body>
</topic>
Anyone whou can help me to make the path relative?

Could this work:
<xsl:value-of select="replace(base-uri(), $folderURI, '') "/>
(did not see this at the comments), since if the problem is the absolute path at the xref, replacing the path with empty value should solve this problem. Or I just understand something terrible wrong. :) This is my tests end result:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE topic
PUBLIC "-//OASIS//DTD DITA Topic//EN" "topic.dtd">
<topic id="to_new_topics">
<title>New topics</title>
<body>
<ul>
<li>
<xref href="en/file3.dita"/>
</li>
<li>
<xref href="file1.dita"/>
</li>
<li>
<xref href="file2.dita"/>
</li>
</ul>
</body>
</topic>
Tested with: XSL, newtopic.xml (to avoid problems and renamed this .xml, not .dita) and all file*.dita files are in the same folder or subfolder.

Related

XSL embed original XML file

I am transforming XML files with XSL to HTML files. Is it possible to embed the original XML file in the HTML output? When yes, how is that possible?
Update 1: To make my need better understandable: In my HTML file, I want a form where I can download the original XML file. Therefore I have to embed the original XML file into my HTML file (e.g. as a hidden input field)
Thanks
If you want to copy the nodes through you can simply do <xsl:copy-of select="/"/> where you want to insert them, however, putting arbitrary XML nodes into HTML does not make sense usually. If you want to serialize an XML document to plain text to render it then you can use solutions like http://lenzconsulting.com/xml-to-string/, for instance:
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:import href="http://lenzconsulting.com/xml-to-string/xml-to-string.xsl"/>
<xsl:output method="html" doctype-public="XSLT-compat" omit-xml-declaration="yes" encoding="UTF-8" indent="yes" />
<xsl:template match="/">
<html>
<head>
<title>Test</title>
</head>
<body>
<section>
<h1>Test</h1>
<xsl:apply-templates/>
<section>
<h2>Source</h2>
<pre>
<xsl:apply-templates mode="xml-to-string"/>
</pre>
</section>
</section>
</body>
</html>
</xsl:template>
<xsl:template match="data">
<ul>
<xsl:apply-templates/>
</ul>
</xsl:template>
<xsl:template match="item">
<li>
<xsl:apply-templates/>
</li>
</xsl:template>
</xsl:transform>
transforms an XML input like
<data>
<item att="value">
<!-- comment -->
<foo>bar</foo>
</item>
</data>
into the HTML
<!DOCTYPE html
PUBLIC "XSLT-compat">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Test</title>
</head>
<body>
<section>
<h1>Test</h1>
<ul>
<li>
bar
</li>
</ul>
<section>
<h2>Source</h2><pre><data>
<item att="value">
<!-- comment -->
<foo>bar</foo>
</item>
</data></pre></section>
</section>
</body>
</html>

catch the first occurrence value

I've the below XML.
<chapter num="1">
<section level="sect2">
<page>22</page>
</section>
<section level="sect3">
<page>23</page>
</section>
</chapter>
here I'm trying to get the first occurrence of <page>.
I'm using the below XSLT.
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ntw="Number2Word.uri" exclude-result-prefixes="ntw">
<xsl:output method="html"/>
<xsl:strip-space elements="*"/>
<xsl:variable name="ThisDocument" select="document('')"/>
<xsl:template match="/">
<xsl:text disable-output-escaping="yes"><![CDATA[<!DOCTYPE html>]]></xsl:text>
<html>
<body>
<xsl:apply-templates/>
</body>
</html>
</xsl:template>
<xsl:template match="chapter">
<section class="tr_chapter">
<xsl:value-of select="//page[1]/text()"/>
<div class="chapter">
</div>
</section>
</xsl:template>
</xsl:stylesheet>
but the output that I get all the page valyes printed. I only want the first one.
Current output.
<!DOCTYPE html>
<html>
<body>
<section class="tr_chapter">2223
<div class="chapter">
</div>
</section>
</body>
</html>
the page values are printed here after <section class="tr_chapter">, i want only 22 but I'm getting 2223
here I'm using //page[1]/text(), because I'm not sure that the page comes within the section, it is random.
please let me know how I can get only the first page value.
here is the transformation http://xsltransform.net/3NzcBsR
Try:
<xsl:value-of select="(//page)[1]"/>
http://xsltransform.net/3NzcBsR/1
Note that this gets the value of the first page element in the entire document.
If you want to search the contents of the chapter context element in your template for the first page descendant then use <xsl:value-of select="descendant::page[1]"/> or <xsl:value-of select="(.//page)[1]"/>.

How to index feed in Google Search Appliance?

i have my atom (list of continent as xml) at this url .../continent/search?view=atom like this:
<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:opensearch="http://a9.com/-/spec/opensearch/1.1/">
<title>List of all continents</title>
<opensearch:totalResults>{{ continents_length }}</opensearch:totalResults>
<opensearch:startIndex>{{ continents.start_index }}</opensearch:startIndex>
<opensearch:itemsPerPage>{{ count }}</opensearch:itemsPerPage>
<opensearch:Query continent="request" searchTerms="" startPage="{{ continents.start_index }}" />
<author><name>My_site</name></author>
<id>urn:domain-id:mysite.com:continent</id>
<link rel="self" href="{{ url }}" />
{% for continent in continents %}
<entry>
<span class="continent_id">{{ continent.continent_id }}</span>
<span class="continent_name">{{ continent.continent_name }}</span>
<span class="list_countries">{{ continent.list_countries }}</span>
</entry>
{% endfor %}
</feed>
When i want to PUT and index my feed in gsa-interface i have used this:
<?xml version="1.0" encoding="utf-8"?>
<entry xmlns="http://www.w3.org/2005/Atom">
<title>continent</title>
<id>urn:domain-id:mysite.com:continent</id>
<author>
<name>admin user</name>
</author>
<link rel="self" href=".../feed/continent"/>
<content type="xhtml">
<div xmlns="http://www.w3.org/1999/xhtml">
<span id="refresh-each">15 12,14,18 * * *</span>
<span id="gsa-datasource">continent</span>
<span id="gsa-feedtype">full</span>
<span id="url">...continent/search?view=atom</span>
<span id="opensearch-pattern">&count=100&startPage=%STARTPAGE%</span>
<ul class="connection">
<li id="userid">user</li>
<li id="password">pass</li>
</ul>
<ul id="metadata">
<li id="continent_id">atom:entry/xhtml:span[#class='continent_id']</li>
<li id="continent_name">atom:entry/xhtml:span[#class='continent_name']</li>
<li id="list_countries">atom:entry/xhtml:span[#class='list_countries']</li>
</ul>
<div id="xsl-content">
<![CDATA[
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:atom="http://www.w3.org/2005/Atom"
xmlns:xhtml="http://www.w3.org/1999/xhtml"
exclude-result-prefixes="atom xhtml">
<xsl:template name="FormatDescription">
<xsl:param name="name"/>
<xsl:value-of select="$name"/>
</xsl:template>
<xsl:template match="atom:entry">
<html>
<body>
<xsl:apply-templates select="atom:entry/xhtml:span" />
</body>
</html>
</xsl:template>
<xsl:template match="atom:entry/xhtml:span">
<xsl:copy-of select="*"/>
</xsl:template>
</xsl:stylesheet>
]]>
</div>
</div>
</content>
</entry>
But when i check the flux of transfered files it return 0 file with error:
ProcessNode: Missing required attribute url. skipping element., skipping record
For the second indexation and the tird one, there is no error, and neither no file !
200 OK Feed continent has been pushed successfully to the Google Search Appliance.
Any suggestion/recommandation ?
Following up on this, the word "feed" is confusing here. A GSA content feed is not like any RSS or Atom feeds. Here's a simplified example (from the documentation):
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE gsafeed PUBLIC "-//Google//DTD GSA Feeds//EN" "">
<gsafeed>
<header>
<datasource>hello</datasource>
<feedtype>incremental</feedtype>
</header>
<record url="http://www.corp.enterprise.com/hello02" mimetype="text/plain">
<content>UPDATED - This is hello02</content>
</record>
</group>
</gsafeed>
As you can see, that's a very specific XML format, not shared with web site update feed formats. The documentation for this is good: http://www.google.com/support/enterprise/static/gsa/docs/admin/70/gsa_doc_set/feedsguide/feedsguide.html
Check out the feed documentation
You need to pass the GSA a feed XML file, not an atom feed.

handling the data in the nested tags and grouping them in xslt

I need some clarification on XSLT how to do the following in XSLT.
I have the source file as this.
<Data>
<additem>
<choice>desc</choice>
<sectiontext>
<a title="google" href="http://google.com" xmlns="http://www.w3.org/1999/xhtml">
<strong>Sample Text</strong>
<ul>
<li><em>aa</em></li>
<li><em>bb</em></li>
<li><em>cc</em></li>
</ul>
</a>
</sectiontext>
</additem>
<additem>
<choice>image</choice>
<files>
<a xmlns="http://www.w3.org/1999/xhtml" title="image location" href="xyz:12-2022">
<img alt="No Image" title="No Image" xlink:href="some image path" xmlns:xlink="http://www.w3.org/1999/xlink"></img>
</a>
</files>
</additem>
<additem>
<choice>Paragraph</choice>
<sectiontext>
<a title="google" href="http://google.com" xmlns="http://www.w3.org/1999/xhtml">
<strong>Sample Text</strong>
<ul>
<li><em>aa</em></li>
<li><em>bb</em></li>
<li><em>cc</em></li>
</ul>
</a>
hello alll
</sectiontext>
</additem>
</Data>
Output:
<Information>
<Section>
<text>
<strong>Sample Text</strong>
<ul>
<li><em>aa</em></li>
<li><em>bb</em></li>
<li><em>cc</em></li>
</ul>
</text>
<link external="http://google.com" title="google"></link>
</Section>
<picture>
<image src="some image path" altText="No Image">
<link local="xyz:12-2022" title="image location"></link>
</image>
</picture>
<Body>
<text>
<hyperlink>
<text>
<strong>Sample Text</strong>
<ul>
<li><em>aa</em></li>
<li><em>bb</em></li>
<li><em>cc</em></li>
</ul>
</text>
<link external="http://google.com" title="google"></link>
</hyperlink>
hello alll
</text>
</Body>
</Information>
Rules:
1.Depending on the choice in addItem/choice, we need to create the tag.
choice -- Desc
desc -- Section
image -- picture
Paragraph----Body
2.Handling tag
Currently tag is wrapping for some other tag.
A.If any element has only <a> in it. For example in the source,
Code in the source:
<sectiontext>
<a title="google" href="http://google.com" xmlns="http://www.w3.org/1999/xhtml">
<strong>Sample Text</strong>
<ul>
<li><em>aa</em></li>
<li><em>bb</em></li>
<li><em>cc</em></li>
</ul>
</a>
</sectiontext>
Need to seperate that tag and create a tag
i. if the "href" in attribute in <a> tag starts with "xyz:" need to add it as "local" attribute in <link> element
ii. If the "href" in the attribute <a> tag starts with "http" need to add it as "external" attribute in <link> element.
ii. "title" attribute in <a> tag remains same in <link>
B.if any element has any other element other than <a> tag.
Code in the source:
<sectiontext>
<a title="google" href="http://google.com" xmlns="http://www.w3.org/1999/xhtml">
<strong>Sample Text</strong>
<ul>
<li><em>aa</em></li>
<li><em>bb</em></li>
<li><em>cc</em></li>
</ul>
</a>
hello alll
</sectiontext>
I need to get the out put as
<text>
<hyperlink>
<text>
<strong>Sample Text</strong>
<ul>
<li><em>aa</em></li>
<li><em>bb</em></li>
<li><em>cc</em></li>
</ul>
</text>
<link external="http://google.com" title="google"></link>
</hyperlink>
hello alll
</text>
Rules:
i. In the all the text inside the <a> tag have to come under the <inlinelink> tag as shown above.
Can any one help how it can be done.
Thank you.
This XSLT 1.0 style-sheet ...
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xhtml="http://www.w3.org/1999/xhtml"
xmlns:xlink="http://www.w3.org/1999/xlink" >
<xsl:output method="xml" indent="yes"/>
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()" />
</xsl:copy>
</xsl:template>
<xsl:template match="/">
<Information>
<xsl:apply-templates select="Data/additem"/>
</Information>
</xsl:template>
<xsl:template match="xhtml:a[../../self::additem]">
<link title="{#title}">
<xsl:if test="starts-with(#href,'http')">
<xsl:attribute name="external"><xsl:value-of select="#href" /></xsl:attribute>
</xsl:if>
<xsl:if test="starts-with(#href,'xyz:')">
<xsl:attribute name="local"><xsl:value-of select="#href" /></xsl:attribute>
</xsl:if>
</link>
</xsl:template>
<xsl:template match="additem[choice='desc']">
<Section>
<text>
<xsl:apply-templates select="sectiontext/xhtml:a/*" />
</text>
<xsl:apply-templates select="sectiontext/xhtml:a" />
</Section>
</xsl:template>
<xsl:template match="additem[choice='image']">
<picture>
<image src="{files/xhtml:a/xhtml:img/#xlink:href}" altText="{files/xhtml:a/xhtml:img/#alt}">
<apply-templates select="files/xhtml:a" />
</image>
</picture>
</xsl:template>
<xsl:template match="additem[choice='Paragraph']">
<Body>
<text>
<hyperlink>
<text>
<xsl:apply-templates select="sectiontext/xhtml:a/*" />
</text>
<xsl:apply-templates select="sectiontext/xhtml:a" />
</hyperlink>
<xsl:apply-templates select="sectiontext/node()[not(self::xhtml:a)]" />
</text>
</Body>
</xsl:template>
</xsl:stylesheet>
... will transform your specified input document into this output document ...
<?xml version="1.0" encoding="utf-8"?>
<Information xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:xlink="http://www.w3.org/1999/xlink">
<Section>
<text>
<strong xmlns="http://www.w3.org/1999/xhtml">Sample Text</strong>
<ul xmlns="http://www.w3.org/1999/xhtml">
<li><em>aa</em></li>
<li><em>bb</em></li>
<li><em>cc</em></li>
</ul>
</text>
<link title="google" external="http://google.com" />
</Section>
<picture>
<image src="some image path" altText="No Image">
<apply-templates select="files/xhtml:a" />
</image>
</picture>
<Body>
<text>
<hyperlink>
<text>
<strong xmlns="http://www.w3.org/1999/xhtml">Sample Text</strong>
<ul xmlns="http://www.w3.org/1999/xhtml">
<li><em>aa</em></li>
<li><em>bb</em></li>
<li><em>cc</em></li>
</ul>
</text>
<link title="google" external="http://google.com" />
</hyperlink>
hello alll
</text>
</Body>
</Information>
Explanation
Each of your rules was taken one by one and used to build a template, starting with the identification of the match condition.

need help with xsl transformation - unwanted text

I'm trying to match just the secondary-content xml tag. but it's outputting text "/ Main cotnent goes here." Why is it outputting text from the masthead and maincontent tag?
xmL:
<xml>
<system-data-structure>
<mastheads>
<masthead>
<image>
<path>/</path>
</image>
<alt/>
</masthead>
</mastheads>
<maincontent>
<content>
<p>Main content goes here. </p>
</content>
</maincontent>
<secondary-content>
<title>
<h2>Secondary Content Title</h2>
</title>
<block>
<path>/</path>
</block>
<content>
<p>Secondary main content goes here. </p>
</content>
</secondary-content>
<secondary-content>
<title></title>
<block>
<content>
<div class="aux-content-box">
<h2 class="aux-content-box">More Information</h2>
<ul>
<li>
Air Force Tuition Assistance
</li>
<li>
Army Tuition Assistance
</li>
<li>
Coast Guard Tuition Assistance
</li>
<li>
Marine Corps Tuition Assistance
</li>
<li>
Navy Tuition Assistance
</li>
<li>
National Guard State Tuition Assistance
</li>
<li>
National Guard Federal Tuition Assistance
</li>
<li>
Reserve Tuition Assistance
</li>
<li>
US Department of Veteran Affairs: Tuition Assistance Top-Up Program
</li>
</ul>
</div>
</content>
<path>/web/current-students/military/military-links-nav</path>
<name>military-links-nav</name>
</block>
<content/>
</secondary-content>
</system-data-structure>
</xml>
xsl:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" encoding="utf-8"/>
<xsl:template match="/system-data-structure">
<xsl:apply-templates select="secondary-content" />
</xsl:template>
<xsl:template match="secondary-content">
Found a learner!
</xsl:template>
</xsl:stylesheet>
output:
/ Main content goes here. Found a learner! Found a learner!
This is a frequently asked question. It's due to XSLT's built-in templates that implicitly drive the processing of various nodes.
Override the built-in template for text nodes with the following template:
<xsl:template match="text()"/>
One reason for the behaviour is with your first template matching line
<xsl:template match="/system-data-structure">
In your XML, the root element is xml, not system-data-structure. This means it doesn't match anything, and this is why the built-in templates are kicking in as described in the previous answer.
Try replacing the above line with this...
<xsl:template match="/xml/system-data-structure">
This should then yield the following output
Found a learner! Found a learner!
It's because in your first template, you're trying to match system-data-structure at the root level. However, xml is the root level in your XML example. Change the match to /xml/system-data-structure:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" encoding="utf-8"/>
<xsl:template match="/xml/system-data-structure">
<xsl:apply-templates select="secondary-content" />
</xsl:template>
<xsl:template match="secondary-content">
Found a learner!
</xsl:template>
</xsl:stylesheet>