Extend an XSLT template to not effect stock templates during processing? - html

Instead of modifying the stock templates that come with many suites, I'd like to extend the stock templates so when the stock template gets upgraded/updated with a new version, I can keep my own XSLT extension/modification of the stock XSLT and use to process with as well. Similar in function to a source code patch file or CSS inheritance.
For example, if the stock XSLT doesn't have enough spaces in the separation between footnotes when processing to HTML, I'd like to add my own XSLT for that footnote that adds a space.

In DocBook XSL stylesheets terms want you want to create is called a “customization layer”.
The basic idea is, put your customizations in a customizations.xsl or whatever file and then use your XSLT engine of choice to call that instead of the stock DocBook XSL driver file; like this:
xsltproc customizations.xsl my-docbook-source.xml
As far what exactly you put into the customizations.xsl file, if all you want to change is some of the user-configurable DocBook XSL params, it’s as easy as:
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:import href="html/docbook.xsl"/>
<xsl:param name="html.stylesheet" select="'corpstyle.css'"/>
<xsl:param name="admon.graphics" select="1"/>
</xsl:stylesheet>
And if you need to replace a whole template:
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fo="http://www.w3.org/1999/XSL/Format"
version="1.0">
<xsl:import href="fo/docbook.xsl"/>
<xsl:template match="lineannotation">
<fo:inline font-style="italic">
<xsl:call-template name="inline.charseq"/>
</fo:inline>
</xsl:template>
</xsl:stylesheet>
So because instead of you directly calling the DocBook XSL driver file from the command line, you call your customization.xsl file and it needs to call the right DocBook XSL driver, then for the href values in, e.g., the <xsl:import href="html/docbook.xsl"/> elements, you just need to put the path to wherever the stock DocBook XSL stylesheets+driver are on your system.
For example, on a Debian system:
<xsl:import href="/usr/share/xml/docbook/stylesheet/docbook-xsl/html/docbook.xsl"/>
Caveats
If you need to make any changes to one of the templates in the stock stylesheets, you copy-paste the entire template into your customization layer and make your changes to the template there.
XSLT doesn’t give any more change-making granularity than that—e.g., you can’t have your layer contain just a two-line patch for part of a template. You have to copy in the whole template.
A consequence of that is, if the upstream maintainers change/fix some other part of original template you made a copy of, your customization layer is not going to pick up that change unless you re-copy the new upstream template in again and make your tweaks to it again.
But that’s probably not going to cause you any problems in practice because these days I think the upstream DocBook XSL templates don’t change very often.
Also note that some of the templates in the DocBook XSL stylesheets are huge—so your layer can end up being a relatively big file even if you only need to make a single-line patch

Yes it is possible for XSLT. Go for <xsl:apply-imports/>.
A template rule that is being used to override another template rule (see 6.4 Conflict Resolution for Template Rules) can use the xsl:apply-imports or xsl:next-match instruction to invoke the overridden template rule.
W3 apply-imports

Related

Adding an invisible document name in XSLT or HTML

I have this XSLT document that has a file name. However for archiving purposes we want the file name to be displayed somewhere else within the code.
Now I used to do this like this:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
sample-xml=".\DOCUMENTNAME.xml"
xmlns:v="urn:schemas-microsoft-com:vml"
xmlns:o="urn:schemas-microsoft-com:office:office">
However we want to get rid of this solution due to new working methods. Now I was wondering if I could place this (literally just the word DOCUMENTNAME) somewhere within the XSL or within the HTML wrapped within it, in a way that it is not visible.
We add this code to a database, through a validator that looks for the documentname and checks for a match. And as only the contents of the code is placed on the database its easier to check back from the database what documentname was uploaded. However this documentname should not be visible in an HTML output.
Maybe add a processing instruction or comment somewhere in the XSLT.
Like:
<?DOCUMENTNAME?>
or:
<!--DOCUMENTNAME-->
They're not invisible, but they definitely won't be included in the output.
Not visible to whom?
Your current solution (with sample-xml) is not valid XSLT: unknown attributes on an XSLT element should be rejected by the processor unless they are in a namespace of their own.
The cleanest way to do this is probably a top-level element (a child of xsl:stylesheet) in a private namespace:
<my:document-name xmlns:my="http://my.company.com/ns/document-id">document.xml</my:document-name>
I don't know if that meets your criteria of being "not visible". It certainly wouldn't be visible in the output of the stylesheet.

Netbeans autocomplete XSLT/HTML

I downloaded Netbeans 8.0.1 to create some XSLT files. Here is a small example:
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>
<h2>My CD Collection</h2>
<table border="1">
<tr bgcolor="#9acd32">
<th style="text-align:left">Title</th>
<th style="text-align:left">Artist</th>
</tr>
<xsl:for-each select="catalog/cd">
<tr>
<td><xsl:value-of select="title"/></td>
<td><xsl:value-of select="artist"/></td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
The autocomplete feature of Netbeans works complete without problems, if you have a simple XSLT file or a simple HTML file. But if you mix up those two files, the autocomplete feature just works for XSLT.
Beginning with the <html> tag, i don't have autocomplete anymore, even not for the XSLT tags at the end of the file.
Does anyone know if this is a bug or just some settings to use autocomplete for HTML and XSLT?
Holy GNU, after a whole afternoon on that, I managed to get both XSL and HTML auto-complete working on the same XSL file.
Download an XSD version of HTML5
HTML is not XML, so we must take a look on XHTML5 (HTML serialized as XML). I've taken the XSD from there
Tell netbeans to use it
The xhtml namespace http://www.w3.org/1999/xhtml must use the XSD we've downloaded. So, in Tools → DTD & XML Schema → User catalog, add a local Schema where the System ID is http://www.w3.org/1999/xhtml and the URI is the xhtml5.xsd you've downloaded.
You may need to restart netbeans (I actually restated it so many times I cannot tell whether it's required or not).
Use the xhtml namespace in the XSL
Now, in the XSL, tell that you're using the xhtml namespace with the attribute xmlns="http://www.w3.org/1999/xhtml" on the root node.
<xsl:stylesheet version="1.0"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>
You could also have added this xmlns attribute to each most-top-level html node (aka, each html node that has no html node in their ancestors). You can also use xmlns:html on the root node, and use <html:*> instead of <*> nodes. It's useful if you have multiple namespaces like HTML+SVG+MathML+XSL.
Enjoy html auto-complete
You should then have the auto completion for html. It requires that you explicitly type the first html tag, but once inside an html tag, the auto complete works (so, if you're making a table inside a xsl:template, you'll still have to type the <table> but once inside, auto complete will suggest things like <caption>, <thead> and so on).
What about auto-complete XSL inside the HTML?
It requires an edit in the xhtml's XSD. We must declare the XSL namespace in the XSD using xmlns:xsl="http://www.w3.org/1999/XSL/Transform" on XSD's root node. Then, we must tell in the XSD that every HTML node can contain an XSL node. This is done by using <xs:any namespace="http://www.w3.org/1999/XSL/Transform" processContents="skip"/> in all elements groups <xs:group>.
Once these edits are done, the XSD says "Every HTML node can contain an element from XSL's namespace", so Netbeans's auto-complete will suggest XSL nodes too.
You can download the edited XSD I'm using here: http://xenos.reinom.com/stackoverflow/xhtml5.xsd
In case you're wondering, I made a long detailed response so you can do the same if you want to mix XSL and SVG or XSL and any other XML-XSDed format.

Is it possible to make a selectable drop down menu using data from an XML file?

I'm trying to create a directory for an address book, and I was wondering if it would be possible to create a selectable drop down menu that would pull the contact data from an XML file. The ideal way I would want it is to have all of the names of the contacts in the drop down menu, and when one is selected the rest of the information would pop up above the drop down, such as Address, Phone Number, and Email.
Either use a server-side language such as PHP to extract the data from the XML and insert it into the HTML document, or use AJAX to pull the XML file to the client then use JavaScript to process it and insert it into the DOM.
There should be libraries/frameworks/plugins/whatever available to parse XML using whatever language you need, if you know how to insert stuff into the HTML document (in the case of PHP) or into the DOM (in the case of JavaScript), you can do this easy.
From what I understand you have an XML document. Using XSLT you create an XHTML file from your XML and that you can display in your browser (XHTML is HTML that is conform to XML rules).
If that is the case then, yes, you can make links using XSLT. But the data needs to be in your XML source file and not in some database.
There is an article that describes it: http://www.ibm.com/developerworks/xml/library/x-tipxslt/index.html
You could attach an XSL to the XML using something like this:
<?xml version="1.0" encoding="ISO-8859-1"?>
<?xml-stylesheet type="text/xsl" href="cdcatalog.xsl"?>
... actual XML content...
If applying the XSL on the XML outputs an HTML page with JavaScript, you can get the actual result.
Outputting JavaScript is a bit of a pain because of character escaping but it can be done.

How best open xml, parse with xslt and show result in browser

I am currently studying ways to present transformed xml files in browsers. My experience with this is minimal, so a number of questions pop up.
I have a transformation test.xslt which transforms input xml to html, and an input file test.xml containing
<?xml version="1.0" standalone="yes"?>
<?xml-stylesheet type="text/xsl" href="test.xslt" ?>
<root>...</root>
which, when opened in IE9, neatly displays the transformed xml contained above in the root element.
Question 1
Is there a processing instruction or similar available to include the source xml into the xml to be opened, somewhat like the following:
<?xml version="1.0" standalone="yes"?>
<?xml-stylesheet type="text/xsl" href="test.xslt" ?>
<... instruction to include source file data.xml>
Question 2
The file opened has extension xml. Is there a way to change file contents so it is valid html, allowing the file to be saved with extension html, so that when opened, the default browser will be selected (simply changing extension to html obviously does not have the desired effect so some structural change is necessary) ?
Question 3
My goal is to query a db to get the data to be parsed by the xslt code. What is the best way to do this (no problem if this includes javascript)?
Question 4
Standard db utilities may export query results in attribute-centered fashion (column names and values being represented as attribute names and values). This may involve pre-parsing the xml from db in order to convert it to parent-child fashion (columns as children instead of attributes). What is the best way to do this pre-parsing (note: I already have the xslt for this; I wonder about the data flow and when/how to run two xslt's in sequence) and then apply test.xslt (preferably without saving intermediate xml result files on the server)?
Question 5
When I open above xml in IE9, this works fine as said. But opening it in Firefox errors (RTF issue, apparently I need to use Firefox's node-set function but I still have to discover which namespace that has), and Opera/Chrome/Safari do not show any content. What exactly are the prerequisites for the various browsers where can I find more information on this?
Q1 If you start by serving an html file which then accesses the xml and xslt via javascript it naturally has access to both the input and the output of the xslt. If you are serving the xml and initiating the transformation using xml-stylesheet pi, then perhaps the best thing to do (depending on what you want to do) is to stuff the original source into the output, then javascript in the generated page can access it if needed, eg
<xsl:template matcj="whatever">
<html>
<head>
<script id="source" type="x-xml-spurce">
<xsl:copy-of select="/"/>
</script>
.... whatever you were going to do
then if you need to access the source in response to a user action on the page, a script can retrieve the script with id source and do whatever is needed. (If there is a possibility of the the source including the string you have to code it a bit more defensively).
Q2 If you want to use the xml-stylesheet API then you have to serve it as xml. However you can instead just serve html and then access the xml and xslt from within a script in the html page using the browsers javascip xslt api. as noted above that is more flexible than the xml-stylesheet mechanism.
Q3 pass
Q4 If you are accessing the xslt from javascript then it is easy to chain the output of one to the input of another without writing back to the server as you just have access to the result as a DOM node (or string, depending)
Answer to question 5: Firefox/Mozilla, Opera, Safari, Chrome all support the EXSLT node-set extension function in the namespace http://exslt.org/common, for IE and MSXML you can use script (imported) inside the XSLT stylesheet to allow it to support that namespace too, see http://dpcarlisle.blogspot.de/2007/05/exslt-node-set-function.html. That way inside the main stylesheet where you need to use the node-set function you don't need to write different code to cater for the different namespaces.

SSI and XSL: xml displayed as a blob

I am building a menu and have it set up so that I use a standard <!--#include virtual = "myDoc.xml" --> SSI tag to include my xml document. The xml document includes the xsl document with <?xml-stylesheet type="text/xsl" href="myOtherDoc.xsl"?>. For some reason the xsl document is not working. The xml is being displayed as a blob.
Unfortunately your XSL transform won't work like that. You'd have to send the XML document alone to the browser where the built in xsl transformer would then reference the stylesheet and perform the transform.
What you've got is an HTML page already being rendered and you're including the XML as just a chunk of xml rendered into the output stream, but the browser won't know to transform it because it doesn't have the:
<?xml-stylesheet type="text/xsl" href="myOtherDoc.xsl"?>
...PI at the start of the page. Remember these are processed by the browser not the server.
You would need to transform the XML server side e.g.
<!-- #include virtual="doMenuXform.asp" -->