xslt transformation from xhtml to custom xml
For a custom application I need to transform xhtml to (custom) xml. After some experimentation I decided to give php5's XSLT functionality a try, but so far I'm unable to transform nested p tags to their xml equivalent.
Basicly we have code like开发者_如何学C this:
<p>Some text</p>
<ol>
<li><p>Some more text</p></li>
..
</ol>
This needs to be transformed to:
<par>Some text</par>
<list>
<li><par>Some more text</par></li>
..
</list>
The real problem is: I need to include inline tags, so xsl:value-of is no option and instead I use xsl:copy-of. So far I have templates for ol|ul and p and the result is this:
<par>Some text</par>
<list>
<li><p>Some more text</p></li>
..
</list>
Anybody some tips how to achieve what I really want just by using a more complex xslt?
Here you go...
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output method="xml" indent="yes"/>
<!-- ============================================== -->
<xsl:template match="/">
<xsl:apply-templates/>
</xsl:template>
<!-- ============================================== -->
<xsl:template match="p">
<xsl:element name="par">
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
<!-- ============================================== -->
<xsl:template match="ol">
<xsl:element name="list">
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
<!-- ============================================== -->
<xsl:template match="li">
<xsl:element name="li">
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
<!-- ============================================== -->
</xsl:stylesheet>
If you start with the identity transform, the general pattern for transforming elements with one name into elements of another is this:
<xsl:template match="old_name">
<new_name>
<xsl:apply-templates select="node()|@*"/>
</new_name>
</xsl:template>
Two things of note:
Generally, unless you know for certain that the element you're transforming has no attributes (or you actively intend to strip off the attributes), you should use the
select
attribute shown; don't just use<xsl:apply-templates/>
. Attributes aren't child nodes, and thus applying templates without aselect
attribute doesn't apply templates to them.Unless you really enjoy typing, there is almost never a reason to use
<xsl:element>
. The exception is when you're generating the output element's name programmatically.
Which, actually, you could do if you wanted to get all fancy-shmancy:
<xsl:template match="*">
<xsl:variable name="new_name">
<xsl:when test="name()='p'>par</xsl:when>
<xsl:when test="name()='ol'>list</xsl:when>
<xsl:when test="name()='li'>item</xsl:when>
<xsl:otherwise><xsl:value-of select="name()"/></xsl:otherwise>
</xsl:variable>
<xsl:element name="{$new_name}">
<xsl:apply-templates select="@*|node()"/>
</xsl:element>
</xsl:template>
You can use nested <xsl:element>
tags to output inline tags as you propose.
Something like:
<xsl:element name="li">
<xsl:element name="p">
some text
</xsl:element>
</xsl:element>
精彩评论