Reputation: 1095
I have the following basic xml file:
<structure>
<part class="Button" id="b1">
<style>
<property name="label">Click me!</property>
</style>
</part>
</structure>
And I am applying XSL to transform this into a html layout with an XForms button/eventually event as well. My xsl:template is the following:
<xsl:template match="part[@class='Button']">
<xforms:trigger>
<xsl:apply-templates select="@accesskey | @tabindex | @size | @style | @id"/>
<xforms:label>
<xsl:value-of select="@label"/>
</xforms:label>
<xsl:apply-templates select="@onclick"/>
<xsl:apply-templates select="*"/>
</xforms:trigger>
</xsl:template>
Ideally, I want the xforms:label to be take the text "Click me!" and disregard the style tag from the xml. So the final result should be:
<xforms:trigger id="b1">
<xforms:label>Click me!</xf:label>
</xforms:trigger>
How do I get there? Thanks in advance!
EDIT:
here is a new example of the another possible scenario of the style
tag:
<structure>
<part class="Button" id="b1"/>
</structure>
<style>
<property part-name="b1" name='label'>Click me!</property>
</style>
Upvotes: 1
Views: 320
Reputation: 23637
To obtain the result you are expecting your template can be much simpler:
<xsl:template match="part[@class='Button']">
<xforms:trigger id="{@id}">
<xforms:label>
<xsl:value-of select="style/property[@name='label']"/>
</xforms:label>
</xforms:trigger>
</xsl:template>
Since your template uses the context created by part
, the path from that context to property
is style/property
. You could also have used less efficient paths like .//property
, */property
. The id
was copied using Attribute Value Templates.
As for your other <xsl:apply-templates>
they seem meaningless unless your code is much different than the one you included in the question. The last one will actually add all child elements to the trigger
which doesn't seem to be what you want.
UPDATE To deal with your second scenario as well, I'll consider you have an input XML such as the one below, with some buttons with nested styles and others that refer to a style which is elsewhere in the document:
<?xml version="1.0" encoding="UTF-8"?>
<structure>
<style>
<property part-name="b2" name="label">Click me NOT!</property>
<property part-name="b1" name="label">Click me!</property>
</style>
<part class="Button" id="b1"/>
<part class="Button" id="b3"/>
<part class="Button" id="b4">
<style>
<property name="label">Click me!</property>
</style>
</part>
</structure>
To refer to the properties in the <style>
block we can create a map selectable by a key, which would be the @part-name
. When you retrieve the element passing the button's ID as a key, you will get the corresponding property
. This line sets up such a map called labels
. It will return a <property>
element which has a name
attribute with the value label
when called with the value of its part-name
attribute:
<xsl:key name="labels" match="property[@name='label']" use="@part-name"/>
This template will generate the code you want for <part>
elements that are Button
if an element exists in the labels
map that has a key equal to its @id
. It will then retrieve that element and use its value:
<xsl:template match="part[@class='Button'][key('labels', @id)]">
<xforms:trigger id="{@id}">
<xforms:label>
<xsl:value-of select="key('labels', @id)"/>
</xforms:label>
</xforms:trigger>
</xsl:template>
This is the full stylesheet which deals with an instance that may contain both scenarios (such as the one listed above):
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xforms="http://www.w3.org/2002/xforms" version="1.0">
<xsl:strip-space elements="*"/>
<xsl:output indent="yes"/>
<!-- Map containing all property[@name='label'] using by their @part-name as key -->
<xsl:key name="labels" match="property[@name='label']" use="@part-name"/>
<xsl:template match="/">
<root>
<xsl:apply-templates select="structure/part"/>
</root>
</xsl:template>
<!-- All <part> elements that do not match the other two templates -->
<xsl:template match="part"/>
<!-- Buttons which have an @id corresponding to a style/property @part-name -->
<xsl:template match="part[@class='Button'][key('labels', @id)]">
<xforms:trigger id="{@id}">
<xforms:label>
<xsl:value-of select="key('labels', @id)"/>
</xforms:label>
</xforms:trigger>
</xsl:template>
<!-- Buttons which have a nested style/property with @name=label -->
<xsl:template match="part[@class='Button'][style/property[@name='label']]">
<xforms:trigger id="{@id}">
<xforms:label>
<xsl:value-of select="style/property[@name='label']"/>
</xforms:label>
</xforms:trigger>
</xsl:template>
</xsl:stylesheet>
With that data it will generate this result:
<?xml version="1.0" encoding="UTF-8"?>
<root xmlns:xforms="http://www.w3.org/2002/xforms">
<xforms:trigger id="b1">
<xforms:label>Click me!</xforms:label>
</xforms:trigger>
<xforms:trigger id="b4">
<xforms:label>Click me!</xforms:label>
</xforms:trigger>
</root>
You can see it working and test the results in this XSLT Fiddle
Upvotes: 1