开发者

XSLT: How to transform partially escaped XML?

I need help transforming an XML file, whose part of it is with escape sequences, into HTML:

<?xml-stylesheet type=text/xsl href=XSL_17.xsl?>
<Root>
  <Book>
    <Author>John smith</Author>
    <Genre>Novel</Genre>
    <Details>&lt;?xml version="1.0" encoding="utf-16"?&gt;&lt;Dets&gt;&lt;Ds&gt;&lt;D DN="Pages" DV="381" /&gt;&lt;D DN="Binding" DV="Hardcover" /&gt;&lt;D DN="Rate" DV="7.8" /&gt;&lt;/Ds&gt;&lt;/Dets&gt;</Details>
  </Book>
  <Car>
    <Year>2010</Year>
    <Name>Charger</Name>
    <Manufacturer>Dodge</Manufacturer>
  </Car>
</Root>

to the following HTML:

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></tit开发者_开发知识库le>
</head>
<body>
    <table>
        <tr>
            <td><strong>Book</strong></td>
        </tr>
        <tr>
            <td><strong>Name</strong></td>
            <td><strong>Value</strong></td>
        </tr>
        <tr>
            <td>Author</td>
            <td>John smith</td>
        </tr>
        <tr>
            <td>Genre</td>
            <td>Novel</td>
        </tr>
        <tr>
            <td>Details</td>
            <td>
                <table>
                    <tr>
                        <td><strong>Name</strong></td>
                        <td><strong>Value</strong></td>
                    </tr>
                    <tr>
                        <td>Pages</td>
                        <td>381</td>
                    </tr>
                    <tr>
                        <td>Binding</td>
                        <td>Hardcover</td>
                    </tr>
                    <tr>
                        <td>Rate</td>
                        <td>7.8</td>
                    </tr>
                </table>
            </td>
        </tr>
    </table>
    <table>
        <tr>
            <td><strong>Car</strong></td>
        </tr>
        <tr>
            <td><strong>Name</strong></td>
            <td><strong>Value</strong></td>
        </tr>
        <tr>
            <td>Year</td>
            <td>2010</td>
        </tr>
        <tr>
            <td>Name</td>
            <td>Charger</td>
        </tr>
        <tr>
            <td>Manufacturer</td>
            <td>Dodge</td>
        </tr>
    </table>
</body>
</html>

I.e., I need to represent both normal XML and escaped XML in HTML tables.


This cannot be done with XSLT unless one implements an XML parser in XSLT.

If you have Saxon, you can use the Saxon extensions saxon:parse() and saxon:transform()


This XSLT produces the output desired

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
xmlns:exsl="http://exslt.org/common" 
extension-element-prefixes="exsl">
<xsl:output indent="yes"/>
<xsl:template match="/Root">
    <html xmlns="http://www.w3.org/1999/xhtml">
        <head>
            <title></title>
        </head>
        <body>                
            <xsl:for-each select="*">
                <table>
                    <tr>
                        <td><strong>
                            <xsl:value-of select="name()"/>
                        </strong></td>
                    </tr>
                    <tr>
                        <td><strong>Name</strong></td>
                        <td><strong>Value</strong></td>
                    </tr>
                    <xsl:for-each select="*">
                        <tr>
                            <td>
                                <xsl:value-of select="name()"/>
                            </td>
                            <td>
                                <xsl:choose>
                                    <xsl:when test="current()[not(contains(.,'xml'))]">
                                        <xsl:value-of select="."/>        
                                    </xsl:when>
                                    <xsl:otherwise>
                                        <xsl:variable name="details"
                                            select="substring-after(.,'?&gt;')"/>
                                        <xsl:variable name="parsedXml_">
                                            <xsl:call-template name="parseXml">
                                                <xsl:with-param name="text" select="$details"/>
                                            </xsl:call-template>
                                        </xsl:variable>
                                        <xsl:variable name="parsedXml" select="exsl:node-set($parsedXml_)"/>
                                        <table>
                                            <tr>                                            
                                                <td><strong>Name</strong></td>
                                                <td><strong>Value</strong></td>
                                            </tr>    
                                            <xsl:for-each select="$parsedXml/Dets/Ds/D">
                                                <tr>
                                                    <td>
                                                        <xsl:value-of select="@DN"/>
                                                    </td>
                                                    <td>
                                                        <xsl:value-of select="@DV"/>
                                                    </td>
                                                </tr>
                                            </xsl:for-each>
                                        </table>
                                    </xsl:otherwise>
                                </xsl:choose>
                            </td>
                        </tr>
                    </xsl:for-each>
                </table>
            </xsl:for-each>
        </body>
    </html>        
</xsl:template>
<xsl:template name="parseXml">
    <xsl:param name="text"/>
    <xsl:choose>
        <xsl:when test="contains($text, '&gt;')">
            <xsl:variable name="topLevelTag">
                <xsl:call-template name="getTopLevelTag">
                    <xsl:with-param name="text" select="$text"/>
                </xsl:call-template>
            </xsl:variable>
            <xsl:variable name="openingTag">
                <xsl:value-of select="$topLevelTag"/>
            </xsl:variable>
            <xsl:variable name="tagName">
                <xsl:call-template name="getTopLevelTagName">
                    <xsl:with-param name="text" select="$text"/>
                </xsl:call-template>
            </xsl:variable>
            <xsl:variable name="closingTag">
                <xsl:value-of select="concat('&lt;/',$tagName,'&gt;')"/>
            </xsl:variable>
            <xsl:variable name="firstNode">
                <xsl:if test="not(contains($topLevelTag,'/&gt;'))">
                    <xsl:value-of select="substring-before(substring-after($text,$openingTag),$closingTag)"/>        
                </xsl:if>
            </xsl:variable>
            <xsl:variable name="afterFirstNode">
                <xsl:choose>
                    <xsl:when test="not(contains($topLevelTag,'/&gt;'))">
                        <xsl:value-of select="substring-after($text,concat($firstNode,$closingTag))"/>        
                    </xsl:when>
                    <xsl:otherwise>
                        <xsl:value-of select="substring-after($text,$topLevelTag)"/>
                    </xsl:otherwise>
                </xsl:choose>
            </xsl:variable>
            <xsl:element name="{$tagName}">
                <xsl:call-template name="createAttributes">
                    <xsl:with-param name="text" select="$topLevelTag"/>
                </xsl:call-template>
                <xsl:call-template name="parseXml">
                    <xsl:with-param name="text" select="$firstNode"/>
                </xsl:call-template>
            </xsl:element>
            <xsl:call-template name="parseXml">
                <xsl:with-param name="text" select="$afterFirstNode"/>
            </xsl:call-template>
        </xsl:when>
        <xsl:otherwise>
            <xsl:value-of select="$text"/>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>
<xsl:template name="getTopLevelTagName">
    <xsl:param name="text"/>
    <xsl:choose>
        <xsl:when test="contains($text, '&gt;')">
            <xsl:variable name="tagWithAttributesWithoutEnd">
                <xsl:value-of select="substring-before($text, '&gt;')"/>
            </xsl:variable>
            <xsl:variable name="tagWithAttributesWithoutBegining">
                <xsl:value-of select="substring-after($tagWithAttributesWithoutEnd, '&lt;')"/>
            </xsl:variable>
            <xsl:variable name="tagName">
                <xsl:choose>
                    <xsl:when test="contains($tagWithAttributesWithoutBegining,' ')">
                        <xsl:value-of
                            select="substring-before($tagWithAttributesWithoutBegining, ' ')"/>
                    </xsl:when>
                    <xsl:otherwise>
                        <xsl:value-of select="$tagWithAttributesWithoutBegining"/>
                    </xsl:otherwise>
                </xsl:choose>
            </xsl:variable>
            <xsl:value-of select="$tagName"/>
        </xsl:when>
    </xsl:choose>
</xsl:template>
<xsl:template name="getTopLevelTag">
    <xsl:param name="text"/>
    <xsl:choose>
        <xsl:when test="contains($text, '&gt;')">
            <xsl:variable name="tagWithAttributesWithoutEnd">
                <xsl:value-of select="substring-before($text, '&gt;')"/>
            </xsl:variable>
            <xsl:value-of select="concat($tagWithAttributesWithoutEnd,'&gt;')"/>
        </xsl:when>
    </xsl:choose>
</xsl:template>
<xsl:template name="createAttributes">
    <xsl:param name="text"/>
    <xsl:choose>
        <xsl:when test="contains($text, '=&quot;')">
            <xsl:variable name="attributeName">
                <xsl:value-of select="substring-before(substring-after($text,' '),'=&quot;')"/>
            </xsl:variable>
            <xsl:variable name="attributeValue">
                <xsl:value-of select="substring-before(substring-after($text,concat($attributeName,'=&quot;')),'&quot;')"/>
            </xsl:variable>
            <xsl:attribute name="{$attributeName}">
                <xsl:value-of select="$attributeValue"/>
            </xsl:attribute>
            <xsl:call-template name="createAttributes">
                <xsl:with-param name="text" select="substring-after($text,concat($attributeName,'=&quot;',$attributeValue,'&quot;'))"/>
            </xsl:call-template>
        </xsl:when>
    </xsl:choose>        
</xsl:template>
</xsl:stylesheet>
0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜