XSL stylesheet keeps Firefox from recognising DTD-defined ids - html

I want a client-side XSL-transformed document with elements targettable (jumpable to) by #foo (URL fragments). Problem is, as soon as I attach the simplest XSL stylesheet, Firefox stops scrolling to the elements. Here's simple code:
test.xml:
<?xml version='1.0' encoding='UTF-8'?>
<?xml-stylesheet type='text/xsl' href='test.xsl'?>
<!DOCTYPE foo [<!ATTLIST bar id ID #REQUIRED>]>
<foo xmlns:html='http://www.w3.org/1999/xhtml' xml:lang='en-GB'>
<html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/>
<bar id='baz'>Baf.</bar>
</foo>
test.xsl:
<xsl:stylesheet version='1.0' xmlns:html='http://www.w3.org/1999/xhtml' xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>
<xsl:template match='/'>
<xsl:copy-of select='.'/>
</xsl:template>
</xsl:stylesheet>
As soon as I uncomment the stylesheet line, /test.xml#baz does nothing. As though the transformation somehow loses some data about elements' identification.
Any ideas? Thanks.

Well the XSLT/XPath data model does not include any DTD and thus your result tree that XSLT creates is a copy of the input without the DTD, thus there is no definition of any ID attributes in the result tree and Firefox has no way of establishing to which element with which attribute #some-id refers.
Usually if you use client-side XSLT in the browser the target format is (X)HTML or SVG or a mix of both where id attributes are known by the browser implementation without needing a DTD. If you want to transform to a result format unknown to the browser then I don't think there is a way to use DTDs for the result tree in Firefox/Mozilla. And I am not sure whether they ever implemented xml:id support so that you could use that instead of defining your own ID attributes.

Martin Honnen's mention of XHTML resulted in experimentation during which I found out that setting the target element's namespace to XHTML's, xmlns='http://www.w3.org/1999/xhtml', does the trick. It doesn't seem very clean, but it doesn't seem as grave as, for instance, setting the whole doctype to XHTML's. So text.xml is now:
<?xml version='1.0' encoding='UTF-8'?>
<?xml-stylesheet type='text/xsl' href='test.xsl'?>
<foo xmlns:html='http://www.w3.org/1999/xhtml' xml:lang='en-GB'>
<html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/><html:br/>
<html:bar id='baz'>Baf.</html:bar>
</foo>
Also relevant might be http://xmlplease.com/xhtmlxhtml I found.
Thanks, all.

Related

Styling inline XML tags with XSLT

This is a similar question to Style inline text along with nested tags with XSLT, but I can't comment to get clarification, so I will elaborate my specific scenario here. I basically have an XML document with the following structure:
<book>
<chapter>
<para>This is some text about <place>New York</place></para>
</chapter>
</book>
I am using XSLT to output XHTML from my XML file, and I want to be able to put span tags or something around the content in the place tag in the example above. The purpose is so that I can style these segments of text with CSS. Following the example I referenced above, I added this:
<xsl:template match="book/chapter/para/place">
<span class="place">
<xsl:apply-templates/>
</span>
</xsl:template>
When I load the XML document in the browser I get the error: "Error loading stylesheet: Parsing an XSLT stylesheet failed." (the stylesheet was loading properly before I added this part)
I'm assuming I lack some basic understanding of how xsl:apply-templates should be used. I would appreciate it if someone could point me in the direction of figuring this out.
Thanks!
The match:
<xsl:template match="book/chapter/para/">
applies templates to all children of the place element, rather than place itself.
Use select within apply-templates instead:
<xsl:template match="/">
<xsl:apply-templates select="book/chapter/para/place"/>
</xsl:template>
In the absence of a select attribute, the xsl:apply-templates instruction processes all of the children of the current node, including text nodes.
A select attribute can be used to process nodes selected by an expression instead of processing all children. The value of the select attribute is an expression. The expression must evaluate to a node-set.
References
XSLT 1.0 Specification

Transform XML in web browser via two transformations to HTML

I tried to transform a XML document within a web browser to HTML via two XSL transformations.
Long story short: XML => XML => HTML
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<?xml-stylesheet type="text/xsl" href="enrich.xsl" ?>
<?xml-stylesheet type="text/xsl" href="overview.xsl" ?>
<project></project>
The first XSL should add some elements to the XML,
the second XSL should transform the result from the first step to HTML.
My target is to get HTML displayed at the end.
Both XSL are transformed separately.
It seems to me that Safari, Firefox and Chrome do not execute more than one processing instruction. Is this true, or am i missing something?
I never tried to execute two seperate transformations in a web browser, but you may try this kind of patterns to do "2 transforms in 1" (this only works with XSLT 2.0, cause of the variable structure) :
<xsl:template match="/">
<!-- You use a variable to store the result of the first transformation.-->
<xsl:variable name="result1">
<!-- You use a mode called transform1 (or whatever) to distinct templates for
transform1 from those of transform2-->
<xsl:apply-templates select="*" mode="transform1"/>
</xsl:variable>
<!-- You execute the second transform on the result variable (you could use a
mode to formally distinct the template from transform2, or you could use default
mode for them) -->
<xsl:apply-templates select="$result1"/>

MSXSL Error and barely any output

I am trying to transform some HTML files to my own XML-format via XSL.
For this purpose I use HTML Tidy to clean up the input files, then transform them to xhtml with html2xhtml and then use a xsl script with msxsl to transform the xhtml files to my own format.
However, the last step is failing with not a error message at all (it is a semantical fail; not a technical ;-)): My output file just contains empty tags.
I had a problem like this before and removed the xmlns attribute from the html tag, what causes nearly all of the online transformers to work with my files correctly. MSXSL now writes the following error message: "Use of default namespace declaration attribute in DTD not supported".
Find the files I use here: http://pastie.org/5483087
Thank you in advance!
Well that is the FAQ with XSLT and XPath 1.0, the elements in your input XHTML document are in a namespace and your XSLT does not take that into account. You need to change it to e.g.
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xhtml="http://www.w3.org/1999/xhtml"
exclude-result-prefixes="xhtml">
<xsl:template match="/">
<stellenausschreibung>
<hochschule><xsl:value-of select="//xhtml:div[#id='contentText']/xhtml:img/#alt" /></hochschule>
<anbieter><xsl:value-of select="//xhtml:p[#id='ad_employer']" /></anbieter>
<typ><xsl:value-of select="//xhtml:h1" /></typ>
<bewerbungsschluss><xsl:value-of select="//xhtml:span[#id='ad_bewerbungsschluss']" /></bewerbungsschluss>
<erscheinungsdatum><xsl:value-of select="//xhtml:span[#class='job_published_at']" /></erscheinungsdatum>
<inhalt><xsl:value-of select="//xhtml:p[#id='ad_job']" /></inhalt>
</stellenausschreibung>
</xsl:template>
</xsl:stylesheet>
The prefix (in my example xhtml) for the XHTML namespace used in the stylesheet can of course be freely chosen but it is necessary to use one as with XSLT/XPath 1.0 a path of e.g. //p always selects p elements in no namespace.

<xsl:value-of select="document(content)//title"/> returns empty node

I'm trying to get title of simple html document to build sitemap. But always return empty value. I debug this and found out that document(content) returns document nodes. It looks like this.alt text http://www.freeimagehosting.net/uploads/f7caf412dc.png But I could not access document(content)/html or something like this. Please help!
Some more code would help, but in such situations the first one to blame is namespace. I can see that your nodes are in the XHTML namespace, but you do not use any namespace prefix in your XPath.
You have to declare namespace prefix in your stylesheet like this:
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:h="http://www.w3.org/1999/xhtml"
>
And then use this prefix in your XPath like this:
document(content)/h:html
If your xml elements are in a namespace, even if it is the default namespace for the document, you must use namespace prefixes in any XPath expressions and template match rules. It is the namespace uri and not the prefix that matters. Note that attributes will not be in the default namespace, they only have a namespace if their name has a prefix.
Additionally, an XPath expression containing // is usually less efficient than one that does not.
<xsl:stylesheet version="1.0"
xmlns:h="http://www.w3.org/1999/xhtml"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<!-- and elsewhere in your stylesheet -->
<xsl:value-of select="document(content)/h:html/h:head/h:title"/>

Problem adding namespaces to MSXML (using setProperty('SelectionNamespaces', ...))

A while back, I asked a question regarding the usage of namespaces in MSXML. At first, I circumvented the whole thing with the XPath *[local-name()]-hack (see my previous post), but having a crisis of conscience I decided to do things the right way. (Doh!)
Consider the following XML:
<?xml version="1.0" encoding="UTF-8"?>
<Root xsi:schemaLocation="http://www.foo.bar mySchema.xsd" xmlns="http://www.foo.bar" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<MyElement>
</MyElement>
</Root>
When I try to add these namespaces using IXMLDOMDocument3.setProperty('SelectionNamespaces', NSString);, I get the following error: "SelectionNamespaces property value is invalid. Only well-formed xmlns attributes are allowed.". When removing the namespace xsi:schemaLocation="http://www.foo.bar mySchema.xsd", everything runs smoothly. What am I doing wrong here? Is there an error in the XML? Is MSXML to blame?
xsi:schemaLocation="..." is not a namespace definition, it is an attribute of the <Root> element which is in xsi namespace.
So removing this from the list of namespaces as you did is already the solution.