正如迈克尔建议的那样,这对于REx来说确实是一个不错的练习。该示例显示了与JSON的一些相似性,但为了演示,让我们猜测一个更简单的 REx 语法:
source ::= item '%' item '%' eof
item ::= '{' ( named-item ( ',' named-item )* )? '}'
| '[' ( item ( ',' item )* )? ']'
| element
named-item ::= name '=' item
<?TOKENS?>
name ::= [a-z]+
element ::= [0-9]+
eof ::= $
将其放入名为 的文件中,并使用 REx 通过配置选项和或使用命令行source.ebnf
从中生成 XSLT 编码的解析器。XSLT
parse tree
-xslt -tree
解析器包含一个名为的函数,该函数p:parse-source
将输入作为字符串接受,并根据上述语法将其转换为具体的语法树。语法树包含每个非终结符或命名标记的元素,以及每个未命名标记的 TOKEN 元素。
然后必须将该语法树转换为目标结构。将生成的解析器从文件source.xslt
导入到下面的 XSLT 中:
<xsl:stylesheet xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"
xmlns:p="source">
<xsl:import href="source.xslt"/>
<xsl:output indent="yes"/>
<xsl:variable name="input" select="'[{c=1,d=2},{cc=11,dd=22}]%{f=4,g=5,h={i=6,j=[7,8]}}%'"/>
<xsl:template match="/">
<xsl:variable name="parse-tree" select="p:parse-source($input)"/>
<xsl:choose>
<xsl:when test="not($parse-tree/self::source)">
<xsl:sequence select="$parse-tree"/>
</xsl:when>
<xsl:otherwise>
<xsl:variable name="item">
<xsl:apply-templates select="$parse-tree/item"/>
</xsl:variable>
<xsl:element name="document">
<xsl:element name="header">
<xsl:sequence select="$item/*[1]/node()"/>
</xsl:element>
<xsl:element name="content">
<xsl:sequence select="$item/*[2]/node()"/>
</xsl:element>
</xsl:element>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="item">
<xsl:variable name="items">
<xsl:apply-templates select="*[not(self::TOKEN)]"/>
</xsl:variable>
<xsl:choose>
<xsl:when test="count($items/*) eq 1">
<xsl:sequence select="$items"/>
</xsl:when>
<xsl:otherwise>
<xsl:element name="item">
<xsl:sequence select="$items"/>
</xsl:element>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="named-item">
<xsl:element name="{name}">
<xsl:variable name="item">
<xsl:apply-templates select="item"/>
</xsl:variable>
<xsl:sequence select="$item/*/node()"/>
</xsl:element>
</xsl:template>
<xsl:template match="element">
<xsl:element name="elt">
<xsl:sequence select="node()"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
在 XSLT 2.0 处理器(例如 Saxon)上运行上述程序将产生所需的结果。