簡體   English   中英

XSLT:如何轉換部分轉義的XML?

[英]XSLT: How to transform partially escaped XML?

我需要幫助將XML文件(其中一部分是轉義序列)轉換為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>

到以下HTML:

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>
</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>

即,我需要在HTML表格中表示普通XML和轉義XML。

除非在XSLT中實現XML解析器,否則無法使用XSLT完成此操作

如果你有Saxon,你可以使用Saxon擴展saxon:parse()saxon:transform()

該XSLT產生所需的輸出

<?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>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM