开发者

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:

  1. 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 a select attribute doesn't apply templates to them.

  2. 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>
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜