xml


How to apply XSL templates to start and finish XML element from different parts of the document


I'm trying to work out how to create a HTML document where sometimes a set of elements from the XML source are 'wrapped' in a bootstrap panel.
The XML describes a vertical form layout. So you have a set of rows which contain a single field. Where there is a PANELSTART field, I want to start a Panel on screen, continue to write out content and then when I hit a PANELEND field, I want to close the panel off with the matching </div>. However XSL doesn't allow this as all elements need a matching end element.
I've tried
<xsl:text>
but that didn't seem to work either. I have an example for illustration.
Source XML:
<?xml version="1.0"?>
<rows>
<row><field type="B><plainValue>B0</plainValue></field></row>
<row><field type="PANELSTART"></field></row>
<row><field type="B"><plainValue>B1</plainValue></field></row>
<row><field type="PANELEND"/></row>
<row><field type="C"><plainValue>C0</plainValue></field></row>
<row><field type="D"><plainValue>D0</plainValue></field></row>
<row><field type="B"><plainValue>B2</plainValue></field></row>
</rows>
XSLT:
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" />
<xsl:template match="field[#type='PANELSTART']">
<div class='panel'>panel header</div>
<div class='panel-body'>
</xsl:template>
<xsl:template match="field[#type='B']">
<p>content goes here</p>
</xsl:template>
<xsl:template match="field[#type='PANELEND']">
</div>
</xsl:template>
</xsl:stylesheet>
Expected Result:
<p>B0</p>
<div class="panel">panel header</div>
<div class="panel-body">
<p>B1</p>
</div>
<p>C0</p>
<p>D0</p>
<p>B2</p>
I'd appreciate your thoughts on how to do this. Unfortunately, I'm not going to be able to change the structure of the XML.
With XSLT 1.0 you can use "sibling recursion":
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="html" indent="yes" version="5.0"/>
<xsl:template match="rows">
<div>
<xsl:apply-templates select="row[1]"/>
</div>
</xsl:template>
<xsl:template match="row[field[#type = 'PANELSTART']]">
<div class="panel">panel header</div>
<div class="panel-body">
<xsl:apply-templates select="following-sibling::*[1]"/>
</div>
<xsl:apply-templates select="following-sibling::row[field[#type = 'PANELEND']][1]/following-sibling::*[1]"/>
</xsl:template>
<xsl:template match="row">
<p>
<xsl:apply-templates/>
</p>
<xsl:apply-templates select="following-sibling::*[1][not(self::row[field[#type = 'PANELEND']])]"/>
</xsl:template>
</xsl:transform>
Online at http://xsltransform.net/bdxtqY/2.
If you are able to use XSLT 2.0, you could potentially make us of xsl:for-each-group together with its group-starting-with attribute
<xsl:for-each-group select="row/field" group-starting-with="field[#type='PANELSTART']">
So, each field with a type attribute of "PANELSTART" forms the start of each group.
Try this XSLT
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output method="html" encoding="UTF-8" indent="yes" />
<xsl:template match="rows">
<xsl:for-each-group select="row/field" group-starting-with="field[#type='PANELSTART']">
<div class='panel'>panel header</div>
<div class='panel-body'>
<xsl:apply-templates select="current-group()" />
</div>
</xsl:for-each-group>
</xsl:template>
<xsl:template match="field[#type='B']">
<p>content goes here</p>
</xsl:template>
<xsl:template match="field[#type='PANELEND']" />
</xsl:stylesheet>
You could probably drop the template matching "PANELEND" though.
Read up on xsl:for-each-group at http://www.xml.com/pub/a/2003/11/05/tr.html
This XSLT ignores all PANELSTART and PANELEND rows (in fact everything not B – but if necessary, it can be reorganized to ignore only PANELSTART and PANELEND). It loops not over fields, but over rows instead. That means that the entire set of field/type B get treated as a single entity, and so you can insert a div around it.
It will work correctly with multiple occurrences of rows (each one will get a div of its own), and will ignore the entire sets of fields when there is no "type B" in it.
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" />
<xsl:template match="rows">
<xsl:if test="row/field/#type='B'">
<div class='panel'>panel header</div>
<div class='panel-body'>
<xsl:apply-templates select="row/field[#type='B']" mode="process" />
</div>
</xsl:if>
</xsl:template>
<xsl:template match="field[#type='B']" mode="process">
[<xsl:value-of select="." />]
</xsl:template>
</xsl:stylesheet>

Related Links

xml file changes its characters when copying from excel
how to create XML file using visual basic
How to get SOAP XML request / response documents in Spring WS?
Split XML file using XSLT 1.0 based on Number of Nodes as counter a value
XMLParser has problems reading UTF8 characters
Using XSLT to create DITA to XML output multiple same element comes under child element to a parent element
Getting “This XML file does not appear to have any style information associated with it” on basic convert
Angular2: Work correctly with XML REST response
how to show archived task in many2many tree view on another model in Odoo9?
how to add pdf file to xslt as html
How to copy child element n times in XML file using XSLT
Generating Flat file output in specific order using XSLT
Passing list of key-value elements to custom JMS Appender
Google Script Export Spreadsheet to XML File
How to get rid of attribute when it has no value, while transforming my XML using XSLT
How get content before specific character in a text using Xpath

Categories

HOME
azure-stream-analytics
css3
twig
character-encoding
camera
error-handling
pclxl
r-googlesheets
mips
onclick
odoo-8
flume
discrete-mathematics
syntaxnet
vimdiff
mel
emoji
stellar.js
intercom
frequency-distribution
capistrano3
dynamic-sql
forgot-password
sse
replication
simpleitk
href
epsilon
roundup
spotipy
bioinformatics
carrierwave
failover
volatile
playstation-portable
github3.py
vue-chartjs
processwire
xajax
docfx
alphabetical
z-notation
diacritics
tasm
magento-1.9.3
doc
plaintext
bindingnavigator
dynamic-linq
truezip
oozie-coordinator
offline.js
shinobi
cudd
actor-platform
lrs
model-associations
hclust
respondcms
shopping
lua-telegram-bot
bizagi
dbamp
nio2
httpruntime.cache
rasterize
fiware-monitoring
ms-access-2000
snackbar
fits
dot.js
xmltype
mmwormhole
cross-join
administration
paw
human-computer-interface
ora-00904
dct
maven-scm
square-bracket
model-driven-development
ebay-lms
script#
workitem
css-reset
joomla-template
wp7test
tree-balancing
patricia-trie
midlet
matlab-load
update-statement
multiplatform
load-time
instantiationexception
vs-android
globals
lxr
visualj#
fail-fast-fail-early
technical-debt
soappy

Resources

Encrypt Message