As per SO standards, I have researched this question in Google and Yahoo, and on W3Schools and other forums for hours before posting here.
All answers I have found so far are geared towards specialized XML languages and other application that are going to read the XML file.
I am not doing this, nor am I writing any other type of code (such as C++, Java, C#, etc; nor am I wanting to use JavaScript).
The small local site I am creating is using only files in HTML, XML, and XSL, and a hand full of image files stored as .jpg and png. There is nothing else.
My little site is running on a local PC based Windows 10 computer with IIS enabled. The site works and other computers can view it in the common web browsers (such as FireFox and Chrome) through the LAN.
The only issue is my coding.
My project is to create a very basic, static site with simple HTML to the output, using nothing but XML and XSLT.
I have an XSL file which defines all of the standard HTML tags in templates [such as (p) (div) (table) (tr) (th) (td), etc] I also have many custom tags, which is why I want to use XML.)
I have reached a point where I want to use the (xsl:element name=" "). For example, I want to define a typical HTML (p style="color:yellow;"), using the (xsl:element name="p").
Here is a small sample of xsl I already have:
<xsl:element name="p">
<xsl:value-of select="p" />
</xsl:element>
This works, and a very plain (p) tag is created in the output and all the text is displayed. But, it has no styling. In the browser output it looks like this
<p>
A paragraph of text in here.
</p>
Having explained the above, my question is (hoping to be very clear), how to do I use the (xsl: element name="p") as shown above to add style attributes to it so my HTML output looks something like this:
<p style="background-color:yellow; font-size: 16pt;">
A paragraph of text in here, which is now black on a yellow background and a 16 point font.
</p>
I have answered my own question, and have included my complete, actual XSLT and some of my XML file for others that may be struggling with this. The short answer is the (xsl:attribute name="style") that is directly below the (xsl:element name="div").
I have included the complete code, which creates a (div) in the output on the left side that remains in a fixed position (meaning it does not scroll). This is a space for a list of links to other chapters used as a menu. The short piece of code beginning with the (xsl:element name="div") and ending with the closing tag (/xsl:element) creates that area, and the (for-each) block reads all the (list-text) and (url) tags [children of the (side_menu_div) tag, then creates a list of links in the (div) area on the side.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="ROOT">
<html>
<head>
<xsl:element name="title">
<xsl:value-of select="title" />
</xsl:element>
</head>
<body style="background-color:#fffc99;">
<xsl:element name="div">
<xsl:attribute name="style">width: 10%; height: 100%; position: fixed; padding-right: 1em; background: white</xsl:attribute>
<xsl:for-each select="/ROOT/side_menu_div/link-text">
<xsl:variable name="index" select="position()" />
<a href="{/ROOT/side_menu_div/url[$index]}">
<xsl:value-of select="." />
</a>
<br/>
</xsl:for-each>
</xsl:element>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
The actual XML
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="/style-sheets/master.xsl"?>
<ROOT>
<title>Player's Core Rulebook</title>
<side_menu_div>
<link-text>Home Menu</link-text>
<url>/methasia_index.html</url>
<br></br>
<link-text>Preamble</link-text>
<url>/rulebooks/_players_core_rulebook/00-Preamble/Preamble.xml</url>
<link-text>Chapter 1</link-text>
<url>/rulebooks/_players_core_rulebook/01-Chapter-01/chapter_1.xml</url>
<link-text>Chapter 2</link-text>
<url>/rulebooks/_players_core_rulebook/02-Chapter-02/chapter_2.xml</url>
<link-text>Chapter 3</link-text>
<url>/rulebooks/_players_core_rulebook/03-Chapter-03/chapter_3.xml</url>
<link-text>Chapter 4</link-text>
<url>/rulebooks/_players_core_rulebook/04-Chapter-04/chapter_4.xml</url>
<link-text>Chapter 5</link-text>
<url>/rulebooks/_players_core_rulebook/05-Chapter-05/chapter_5.xml</url>
<link-text>Chapter 6</link-text>
<url>/rulebooks/_players_core_rulebook/06-Chapter-06/chapter_6.xml</url>
<link-text>Chapter 7</link-text>
<url>/rulebooks/_players_core_rulebook/07-Chapter-07/chapter_7.xml</url>
<link-text>Chapter 8</link-text>
<url>/rulebooks/_players_core_rulebook/08-Chapter-08/chapter_8.xml</url>
<link-text>Chapter 9</link-text>
<url>/rulebooks/_players_core_rulebook/09-Chapter-09/chapter_9.xml</url>
<link-text>Chapter 10</link-text>
<url>/rulebooks/_players_core_rulebook/10-Chapter-10/chapter_10.xml</url>
<link-text>Appendix</link-text>
<url>/rulebooks/_players_core_rulebook/11-Appendix/Players_Core_Rulebook_Appendix.xml</url>
</side_menu_div>
Related
i am making a website that will feature many articles that will always be changing, i am trying to find a way to quickly change the text in these articles as i am the only person who knows the code in the company.
I was thinking of having a text document or something that has the articles text and when it gets changed so does the text on the site.I just dont know how to implement this.
sorry if its hard to understand what i mean, im not too familiar with sleep these days.
You don't need any dynamic server code like the other answers are suggesting. Either a "static site generator" (there are uncountably many, but that should give you something to Google if my main answer doesn't satisfy you) or a client-side scripting.
XSLT was designed for this exact problem. It can be run client-side or server-side with xsltproc (for compatibility with dumb clients). XSLT 1.0 is well-supported by all common browsers, though if you need EXSLT extensions in IE you had to add shims. Note that Webkit-based browsers can't do XSLT on file:// URLs, either set up a local HTTP server or use Firefox.
I have a minimal example site set up here that includes multiple files in
one page: https://o11c.github.io/foo-test/foo-root.xml
foo-style.xml:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/index">
<html>
<body>
<h2>Merge test</h2>
<table border="1">
<tr>
<th>Attr</th>
<th>Value</th>
</tr>
<xsl:apply-templates select="document(include/#name)"/>
</table>
</body>
</html>
</xsl:template>
<xsl:template match="root">
<xsl:for-each select="foo">
<tr>
<td><xsl:value-of select="#x"/></td>
<td><xsl:value-of select="text()"/></td>
</tr>
</xsl:for-each>
</xsl:template>
<xsl:template name="identity">
<xsl:copy>
<xsl:for-each select="node()|#*">
<xsl:call-template name="identity"/>
</xsl:for-each>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
foo-root.xml:
<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="foo-style.xslt"?>
<index>
<include name="foo-1.xml"/>
<include name="foo-2.xml"/>
</index>
foo-1.xml:
<?xml version="1.0"?>
<root>
<foo x="a">aa</foo>
<foo x="b">bb</foo>
<foo x="c">cc</foo>
</root>
foo-2.xml:
<?xml version="1.0"?>
<root>
<foo x="d">dd</foo>
<foo x="e">ee</foo>
<foo x="f">ff</foo>
</root>
Further resources:
XSLT 1.0 spec
XPath 1.0 spec - in particular the function reference
EXSLT extensions - node-set in particular is very useful.
xsltproc webpage
You could use wordpress, if you are building the site from scratch and not adding to an existing one. This will allow you to edit articles in a user friendly interface that will allow you to style the text and will be easier for other people in the company to edit as well. It's very fast to set up.
Or you could just keep the written text in the HTML file itself, but this may make it harder to maintain and style, and those not technical savvy may not be able to edit it or will end up breaking it.
Well you might do this using php and Mysql
You can easily display save the articles in mysql and you could create a simple user interface for the people respnsible for editing the code to edit it too easy
I'm using XSLT stylesheet to render a simple XML file of the text of Alice in Wonderland into HTML.
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="Alice.xsl"?>
<book>
<title>Alice's Adventures in Wonderland</title>
<text>
<chapter>
<chapter_heading>Chapter I. Down the Rabbit-Hole</chapter_heading>
<p>Alice was beginning to get very tired of sitting by her sister on the
bank, and of having nothing to do: once or twice she had peeped into the
book her sister was reading, but it had no pictures or conversations in
it, 'and what is the use of a book,' thought Alice 'without pictures or
conversations?'</p>
<p>So she was considering in her own mind (as well as she could, for the
hot day made her feel very sleepy and stupid), whether the pleasure
of making a daisy-chain would be worth the trouble of getting up and
picking the daisies, when suddenly a White Rabbit with pink eyes ran
close by her.</p>
</chapter>
</text>
</book>
Simple stuff. And we're trying to output just the Title of the Chapter and the paragraphs into an tag in HTML using this code:
<?xml version="1.0" encoding="UTF-8"?><!-- DWXMLSource="http://www.w3.org/1999/XSL/Transform" -->
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" encoding="UTF-8"/>
<xsl:template match="/">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<article>
<xsl:apply-templates/>
</article>
</body>
</html>
</xsl:template>
<xsl:template match="title"/>
<xsl:template match="chapter">
<h3>
<xsl:apply-templates select="chapter_heading"/>
</h3>
<div class="paragraph">
<xsl:apply-templates select="p"/>
</div>
</xsl:template>
</xsl:stylesheet>
But once the XML file is opened in a browser, all of the separate 'p' tags in the XML are just grouped together into one large 'div' in the HTML.
Our group is obviously very new to XSL, but as far as we've been able to research, we don't tell why this isn't working smoothly. Any help would be appreciated!
You dind't define a template for the <p> element.
You effectively applied templates on <p> elements with your <xsl:apply-templates select="p"/> but without a specific template for them, the xslt processor simply applies default template wich just output the text content of the elements. This is why you got everything in the same <div class='paragraph'> element (which is the parent element you create before applying template on <p>).
I guess, you want to preserve the <p> elements as they are in the input, then just add the template declaration below and you'll get your <p> in your output.
<xsl:template match="p">
<xsl:copy-of select="."/>
</xsl:template>
As a general design template, when you want to copy an input with some layout features, use a "copy template pattern" with this default declarations which will work for any input (<p> <citation> and so on).
<!-- This match will select any element without any other template matching (the `<p>` elements in your case.)-->
<xsl:template match="*">
<!-- First copy the element itself -->
<xsl:copy>
<!-- Then copy the attributes if any. -->
<xsl:copy-of select="#*">
<!-- Finally apply-templates on childs, then text nodes will be outputed by default templates, and elements would go through your template flow allowing to be copied or formatted if needed (with specific templates) -->
<xsl:apply-templates select="node()"/>
</xsl:copy>
</xsl:template>
I have a XSLT file which is used for html to xsl-fo conversion using fop engine.
It has templates for HTML elements as shown below
<pre>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fo="http://www.w3.org/1999/XSL/Format"
version="2.0">
<xsl:template match="html">
//handle html element
</xsl:template>
<xsl:template match="head/title">
//handle head/title elements
</xsl:template>
</xsl:stylesheet>
</pre>
I need to convert all kinds of HTML files provided as input to the processor.
HTML files without namespace are processed without any issues.
However, some HTML files have name space (<html xmlns="http://www.w3.org/1999/xhtml">)
in which case the fop processor is throwing exceptions.
What is the best way to handle this sort of cases?
Can i create some template which ,based on the local-name(), call the correct template?
My preference in this kind of situation is to normalize the input before doing anything else, in a separate pass. This could be done with a template rule something like this:
<xsl:template match="*">
<xsl:element name="lower-case(local-name())">
<xsl:copy-of select="#*"/>
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
You can do something like this:
<xsl:template match="*[local-name()='html' or local-name()='HTML']">
//handle html element
</xsl:template>
that will match html or HTML elements in any namespace.
Unfortunately HTML can have a LOT of variations, and also contains non-valid XML (e.g. tags that are not closed). If you want a real general solution you need a HTML parser.
I have an XSLT that I input to a 3rd party application. This application displays the result of that XSLT as a web page in their application.
I have a dynamic HTML document that I want to display in that application. How can I "read" the HTML document via an XSLT document such that whenever the html document is updated, the XSLT will read the new file?
If I'm not being clear, to convey the idea, my xslt would read something like this:
<xsl:stylesheet>
<xsl:output method="html"/>
<xsl:template match="Something">
<!-- Stuff is done here -->
</xsl:template>
<xsl:ReadExternalDocument filePath="my/path/document.html" />
</xsl:stylesheet>
I've come across the Document() function, but it seems to destroy my tags. That is, I would like to include the child tags of the parent element in the output.
As Tomalak suggested, the document function is the way to go. I read in the external HTML document using the document() with the copy-of node. copy-of does a deep-copy, including tags, to obtain the whole external HTML document. The code looks like this:
<xsl:stylesheet ... >
<xsl:output method="html"/>
<xsl:template match="/">
<xsl:copy-of select="document('ExternalDocument.html')" />
</xsl:template>
</xsl:stylesheet>
I'm exploring the XML -> XSLT -> HTML meme for producing web content. I have very little XSLT experience.
I'm curious what mechanisms are available in XSLT to handle abstractions or "refactoring".
For example, with generic HTML and a service side include, many pages can be templated and decomposed to where there are, say, common header, nav, and footer segments, and the page itself is basically the body.
The common markup languages, JSP, PHP, ASP, go as far as to allow all of those segments to have dynamic content (such as adding the user name to every header block).
JSP goes even farther by allowing you to create Tag files, which can accept arguments to be used when generating the content, and even surround and work on content within the tags themselves.
I'm curious similar functionality is done within XSLT. What facilities are there to make reusable block of XSLT for things like creating HTML pages?
For my own project, this is how I divided up my pages. There was a template.xsl file which was imported
by each of my XSLs. Most pages just had template.xsl, but some pages such as cart, etc. needed their own
because of the different kind of data they were parsing.
<page title="Home">
<navigation>
<!-- something here -->
</navigation>
<main>
<!-- something here -->
</main>
</page>
This is a snippet from my template.xsl. I threw in all the common stuff in here, and then gave the opportunity
for my pages to add their own information through call-template.
<xsl:template match="/page" name="page">
<html>
<head>
<title><xsl:value-of select="(#title)" /></title>
<xsl:call-template name="css" />
<xsl:call-template name="script" />
</head>
<body>
<xsl:call-template name="container" />
</body>
</html>
</xsl:template>
An example of how my css tag would respond. Note that it calls css-extended. css only
had the the common css' that would apply across all pages. Some pages needed more. Those
could override css-extended. Note that is needed because call-template will fail if a
page calls a template but doesn't define it anywhere.
<xsl:template name="css">
<link rel="stylesheet" type="text/css" href="{$cssPath}reset.css" />
<link rel="stylesheet" type="text/css" href="{$cssPath}style.css" />
<link rel="stylesheet" type="text/css" href="{$cssPath}layout.css" />
<xsl:call-template name="css-extended" />
</xsl:template>
<!-- This is meant to be blank. It gets overriden by implementing stylesheets -->
<xsl:template name="css-extended" />
My container would work in a similar manner-- common stuff was defined and then each page
could just provide an implementation. A default implementation was in the XSL. (in content)
<xsl:template name="container">
<div id="container">
<xsl:call-template name="header" />
<xsl:call-template name="content" />
<xsl:call-template name="footer" />
</div>
</xsl:template>
<xsl:template name="content">
<div id="content">
<div id="content-inner">
<xsl:call-template name="sideBar" />
<xsl:call-template name="main" />
</div>
</div>
</xsl:template>
<xsl:template name="main">
<div id="main">
<xsl:apply-templates select="main" />
<xsl:call-template name="main-extended" />
</div>
</xsl:template>
<!-- This is meant to be blank. It gets overriden by implementing stylesheets -->
<xsl:template name="main-extended" />
<xsl:template name="footer">
<div id="footer">
<div id="footer-inner">
<!-- Footer content here -->
</div>
</div>
</xsl:template>
It worked quite beautifully for me. If there are any questions I can answer for you, let me know.
Templates, Includes.
Xsl is very different from any other programming language. Its rule based.
I recommend you to read something about Xslt and then ask a bit more spedific.
There are both xsl Include and Import statements that you can use to abstract away portions of the page. XSLT itself is very much the kind of thing that can reproduce tag file type behavior. You edit your xml data files with the tags you want. Meanwhile, your xsl templates are going to know what do to with those tags then they encounter them.
You can give templates names and then call them via 'call-template'
In XSLT 2.0 you can create your own functions (although I find the syntax tortuous)
A wonderful area to explore is using XSLT to generate XSLT stylesheets. This lets you automate common conversion scenarios where 90% of the stylesheet is boilerplate. In order to do this you need to become familiar with 'namespace-alias'. Its a great way to expand your knowlege of the language.
XSL is based on templating.
XML data can be "re-used" at three-levels. At the most basic level you can <xsl:for-each /> through XML.
Note: For-each in XSL is not looping through the data, it's just matching the data. Also when your "inside" a for-each your inside that "context" of the XML (which is like the concept of "scope" in programming)
An example of using and re-using a for-each
<xsl:for-each select="/xml/data/here">
... do some stuff ...
</xsl:for-each>
<xsl:for-each select="/xml/data/here">
... do some DIFFERENT stuff ...
</xsl:for-each>
The for-each nodes are contained within template nodes (2nd level of reuse). There are two types of template nodes: Match and Named. Match template nodes, act like the for-each node mentioned above, but are automatically called by the template engine if any nodes are matched when XSL processing starts. Match template nodes can also be explicitly applied. On the other hand Named template nodes are always explicitly applied and can be thought of as like functions.
Example of a Match template which will Always be called (because a root node will always exist)
<xsl:template match="/">
... do some stuff ...
</xsl:template>
A Match template calling another match template explicitly
<xsl:template match="/">
<xsl:apply-templates select="xml/data/too" />
</xsl:template>
<xsl:template match="xml/data/too">
... do something ...
</xsl:template>
Note: In order for the Match template to work, the XML Node it is matching needs to exist. If it doesn't there is no match, so that template is not called.
Example of a Named template
<xsl:template name="WriteOut">
... data with NO Context Here ...
</xsl:template>
Or calling a Named template from a Matched template
<xsl:template match="/">
<xsl:call-template name="WriteOut" />
<xsl:template>
Note: You can mix and match where you call matched and named templates from, you just have to watch what context you are in.
All of template nodes are held in XSL Stylesheets, and you can include and import various stylesheets. For example you can hold all of the templates dealing with HTML header nodes in one template and all of the templates dealing with the HTML body nodes in another. Then you can create one stylesheet that includes both Header and Body stylesheets.
Example of an include node
<xsl:include href="header.xsl" />
In conclusion there are three ways to abstracting chunks of data, through for-eaching, through templating or through including stylesheets.
XSLT is powerful, but it is very different from most programming languages and it is quite limited in what it makes available to you, so things that you have built-in with another language may need some quite complex xsl manipulation to work with. I found the cheatsheet from here useful when I was going through a lot of XSLT work a couple of weeks back.
Don't expect that XSLT will do things in a particular way and you probably can find good ways of doing those things, but if you have too much of a set idea about how something should work it's easy to get stuck.