I try to generate a single page application based on alpine.js.
The HTML should be generate form XML descriptions via XSLT.
Example for required output.
<div #notify="alert('Hello World!')">
<button #click="$dispatch('notify')">
Notify
</button>
</div>
My try to generate this via xsl:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" indent="yes" />
<xsl:template match="test">
<div>
<xsl:attribute name="#notify">
<xsl:text>alert('Hello World!')</xsl:text>
</xsl:attribute>
<button>
<xsl:attribute name="#click">
<xsl:text>$dispatch('notify')</xsl:text>
</xsl:attribute>
Notify
</button>
</div>
</xsl:template>
</xsl:stylesheet>
Imput XML:
<?xml version="1.0"?>
<test/>
Result:
Error in xsl:attribute/#name on line 8 column 39 of alpina.xsl: XTDE0850 Attribute name {#notify} is not a valid QName
I don't know alpine.js, but we see similar problems with other "XML-like" or "HTML-like" formats.
XSLT works on the XDM data model, which defines concepts such as elements and attributes, and defines rules for the content, for example rules for element and attribute names (which don't allow them to start with "#"). If you want to generate something like the output you have shown, you first need to define a representation of this content using the XDM data model. This might include a mapping from XDM attribute names to alpine attribute names (for example, you could use the XDM attribute name __notify to represent the alpine attribute name #notify).
Then (a) your stylesheet would generate an XDM attribute named __notify, and (b) you would need a custom serialization method that serialises __notify as #notify.
The Saxon serialization machinery is highly customizable. If you want to integrate this fully, you could register a SerializerFactory with the Saxon Configuration, that registers a user-defined serialization method, and uses a subclass of XmlEmitter or HtmlEmitter to customize the output. For example you could override the writeAttribute method so it outputs __notify="xxxx" as #notify="xxxx".
Related
Suppose the following xhtml
...
<a>
skipcontent_1
<div>
skipcontent_2
</div>
<div id='info'>
showcontent_3
<div>
showcontent_4
</div>
<c>
skipcontent_5
</c>
</div>
</a>
...
I would like to have only the text from those div elements, which have id='info' or are below of such a div
So the result should look like this
showcontent_3
showcontent_4
(ident/newlines are not important)
I tried hard to have an identity transformation acting like this, but already failed by letting it ignore the nodes/content "outside" of a <div id='info'/> section...
It sounds to me like your problem is a better fit for a stylesheet without an identity template. This stylesheet satisfies your requirements given that input:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="text()" priority="1">
<!-- Do not output text normally -->
</xsl:template>
<xsl:template match="div/text()[ancestor::div[#id = 'info']]" priority="2">
<xsl:copy/>
</xsl:template>
</xsl:stylesheet>
To deconstruct a bit:
Generally, you want to output nothing. That's the reason for the first template, since default behavior in XSLT for a text node is to copy it to output.
You do want certain text nodes to be copied to output, so the second template handles those. The match expression finds text nodes that satisfy two things: (1) that they are a text node that is a child of a div element (div/text()) and (2) that they are somewhere beneath a div element that has the #id attribute set to "info" ([ancestor::div[#id = 'info']]).
(The second template's match expression could be (more or less) equivalently written as div[#id = 'info']//text()[parent::div].)
How to customize or change the contact page of dspace 5.5 XMLUI? What files or configuration should I change?
To add additional content to the page you have two options:
One option is to customize Contact.addBody. For example:
public void addBody(Body body) throws ... {
[...]
contact.addPara("For urgent matters call 555-666-777.");
}
Use the IDE autocompletion to see what kind of elements you can add. There are equivalents to the basic HTML elements. See DRI Schema Reference to understand it better.
The other option is to add the content through an XSL file:
First, create dspace-xmlui-mirage2/src/main/webapp/xsl/aspect/artifactbrowser/contact.xsl (assuming Mirage 2 theme) with the following content:
<xsl:stylesheet
xmlns:i18n="http://apache.org/cocoon/i18n/2.1"
xmlns:dri="http://di.tamu.edu/DRI/1.0/"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
xmlns="http://www.w3.org/1999/xhtml"
exclude-result-prefixes="i18n dri xsl">
<xsl:output indent="yes"/>
<xsl:template match="dri:div[#id='aspect.artifactbrowser.Contact.div.contact']">
<xsl:apply-templates />
<!-- Add here any additional HTML: -->
<p>
For urgent matters call 555-666-777.
</p>
</xsl:template>
</xsl:stylesheet>
Then, add a reference at the end of dspace-xmlui-mirage2/src/main/webapp/xsl/theme.xsl:
<xsl:import href="aspect/artifactbrowser/contact.xsl"/>
I have the following snippet in rules.xml
<!-- Fix search box to honour Plone rules-->
<replace css:theme="form#search">
<form action="http://localhost:8080/LS/search" name="form1" id="search">
<input type="text" name="SearchableText" onclick="make_blank();" onblur="keep_search();" class="search_text_style content_text2"/>
<input type="image" src="++resource++lsm/images/template/search.png" width="22" height="22" class="search_btn" />
</form>
</replace>
How one can pass dynamic attributes to XSL so that I cat set to be real URL based on the Plone site object?
I can do this by providing helper views, modify XDVTransform, etc. but I'd like to first know what's the recommended approach here.
Note that in plone.app.theming / Diazo, you'll be able to define parameters using TAL and pass them to your theme.
I think in this case, I'd just grab the actual search URL (or the home URL) from the content with an attribute value-of.
I think you need a global <xsl:param> for this.
Typically, the value of a global parameter is set by the initiator of the transformation just before the transformation is initiated. This is a recognized general way of passing to the XSLT transformation values that are not static (known at the stylesheet compilation time).
Here is an example:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:param name="pUrl" select="'http://www.cnn.com'"/>
<xsl:template match="/">
<t href="{$pUrl}"/>
</xsl:template>
</xsl:stylesheet>
when this transformation is applied on any XML document (not used), the result is:
<t href="http://www.cnn.com" />
How a global parameter value is set is implementation-dependent and varies from one XSLT processor to another. Read the documentation of your XSLT processor to get the knowledge how to do this.
I am using about a dozen XSLT files to provide a large number of output formats. At the moment the user has to know the extension of the file format being exported to e.g. RTF, HTML, TXT.
I would also like to use parameters to allow more options. If I can embed the metadata in the XSL file itself then I can pick up the details by scanning through the files.
Here is what I am thinking about. In this example the program would have to parse the comments for the required information.
<?xml version="1.0" encoding="UTF-8"?>
<!-- Title: Export to Rich Text Format -->
<!-- Description: This Stylesheet converts to a Rich Text Format format which may be used in a word processor such as Word -->
<!-- FileFormat: RTF -->
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:param name="CompanyName"/> <!-- Format:String, Description: Company name to be inserted in the footer -->
<xsl:param name="DateDue"/> <!-- Format:Date-yyyy-mm-dd, Description: Date Due -->
<xsl:param name="IncludePicture">true</xsl:param><!-- Format:Boolean, Description: Do you want to include a graphical representation? -->
<xsl:template match="/">
<!-- Stuff -->
</xsl:template>
</xsl:stylesheet>
Are there any standards out there? Do I need to butcher more than one (Dublin Core with a smattering of XML Schema)?
P.S. the project this is being applied to is Argumentative.
Here is what I am thinking about. In
this example the program would have to
parse the comments for the required
information.
You don't need to code the metadata within comments.
Metadata can be specified as part of the XSLT stylesheet using ordinary XML markup -- as rich in structure and meaning as we need.
Here is an example how to do that:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:meta="my:meta">
<xsl:output method="text"/>
<meta:metadata>
<title>Title: Export to Rich Text Format </title>
<description>
This Stylesheet converts to a Rich Text
Format format which may be used in a word processor
such as Word
</description>
<fileFormat>RTF</fileFormat>
<parameters>
<parameter name="CompanyName" format="xs:string"
Description="Company name to be inserted in the footer"/>
<parameter name="DateDue" format="xs:date"
Description="Date Due"/>
<parameter name="IncludePicture" format="xs:boolean"
Description="Do you want to include a graphical representation?"/>
</parameters>
</meta:metadata>
<xsl:param name="CompanyName"/>
<xsl:param name="DateDue"/>
<xsl:param name="IncludePicture" select="true"/>
<xsl:variable name="vMetadata" select=
"document('')/*/meta:metadata"/>
<xsl:template match="/">
This is a demo how we can access and use the metadats.
Metadata --> Description:
"<xsl:copy-of select="$vMetadata/description"/>"
</xsl:template>
</xsl:stylesheet>
when this transformation is applied on any XML document (not used), the result is:
This is a demo how we can access and use the metadats.
Metadata --> Description:
"
This Stylesheet converts to a Rich Text
Format format which may be used in a word processor
such as Word
"
Do note:
Any element that is in a namespace (of course not the no-namespace and not the xsl namespace) can be specified at the global level of any xslt stylesheet.
Such elements can be accessed using the xslt function document().
I have written an xslt that reads some xml file names and does some operations on them.
I use a for-each to work them one-by-one. I have each path inside a parameter $path.
But now I would like to output the result of applying an external stylesheet to those files. I would write something like
<div> <something like xsl-transform($extern-xslt,$path)> </div>
to have the result tree of the transformation inside the main html output.
It is possible?
You could import the external stylesheet to your main stylesheet with xsl:import, and then just apply templates to that external XML file, which you can load with the document function.
<div><xsl:apply-templates select="document($path)"/></div>
If the templates in the external stylesheet would collide with the templates in the main stylesheet, you can use a different mode for them.
You can use the document() XPath function to load an external XML file. This returns a node-set which can be parsed with a <xml:apply-templates> call. Including an external stylesheet can be accomplished by using an <xsl:include> tag.
<xsl:include href="$external"/>
<xsl:apply-templates select="document($path)"/>
See also the documentation for document()
I have written an xslt that reads
some xml file names and does some
operations on them. I use a for-each
to work them one-by-one. I have each
path inside a parameter $path.
But now I would like to output the
result of applying an external
stylesheet to those files
The solution consists of these ingredients:
Use the standard XSLT document() function to load and access the external XML document.
Import the external stylesheet, using an <xsl:import> instruction.
The templates in the external stylesheet must be in a special mode, not used by the primary stylesheet.
At the place where the result of the "external transformation" is wanted, issue <xsl:apply-templates> selecting the necessary nodes of the external document (usually the root node /, or the top element /*). The mode, specified on the <xsl:apply-templates> should be the same as the mode used in the external stylesheet.
Here is a small, simplified example (No external stylesheet is imported, the "external document" is embedded in the stylesheet, and no mode is used):
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:my="my:my"
>
<!-- <xsl:import href="myExternal.xsl"/> -->
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<my:div>
<h2>Weather</h2>
<p >It will be raining today</p>
</my:div>
<xsl:template match="node()|#*">
<xsl:copy>
<xsl:apply-templates select="node()|#*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="insertContents">
<xsl:apply-templates select="document('')/*/my:div/*"/>
</xsl:template>
</xsl:stylesheet>
When this transformation is applied on this XML document:
<html>
<h1>Today's News </h1>
<insertContents/>
</html>
the desired result is produced:
<html>
<h1>Today's News </h1>
<h2 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:my="my:my">Weather</h2>
<p xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:my="my:my">It will be raining today</p>
</html>
Note that the extraneous namespaces above are only due to the simplifications of this example -- they will not be generated if the external XML document were in its own file.