Michael が示唆したように、これは確かに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 ::= $
それを という名前のファイルに入れ、source.ebnf
オプションXSLT
およびを構成するparse tree
か、コマンド ライン を使用して、REx を使用してそこから XSLT コードのパーサーを生成します-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 など) で実行すると、目的の結果が生成されます。