XSL 中的递归替换
Posted
技术标签:
【中文标题】XSL 中的递归替换【英文标题】:Recursive replace in XSL 【发布时间】:2018-12-29 11:16:30 【问题描述】:我有以下 XML:
<?xml version="1.0" encoding="utf-8"?>
<routes>
<route name="/path/id/name">
<location>~ ^/path/id/name$</location>
<methods>
<method>GET</method>
</methods>
<parameters>
<parameter name="id">[a-zA-Z0-9]+</parameter>
<parameter name="name">[a-z]+</parameter>
</parameters>
</route>
</routes>
我想得到以下输出:
~ ^/path/(?<id>[a-zA-Z0-9]+)/(?<name>[a-z]+)$
但目前我有像 ~ ^/path/(?<id>[a-zA-Z0-9]+)/name$~ ^/path/id/(?<name>[a-z]+)$
这样使用 XSL 的输出:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:php="http://php.net/xsl"
version="1.0"
>
<xsl:output method="text" encoding="utf-8"/>
<xsl:template match="routes">
<xsl:apply-templates select="route"/>
</xsl:template>
<xsl:template match="route">
<xsl:apply-templates select="parameters"/>
</xsl:template>
<xsl:template match="parameters">
<xsl:apply-templates select="parameter"/>
</xsl:template>
<xsl:template match="parameter">
<xsl:value-of select="php:function('str_replace', concat('', @name, ''), concat('(?<', @name, '>', text(), ')'), string(./../../location))"/>
</xsl:template>
</xsl:stylesheet>
我如何使用重用结果并将其传递给下一次运行?
【问题讨论】:
【参考方案1】:您需要首先选择第一个参数,然后使用它进行替换。如果有以下参数,则递归选择它,将转换后的文本作为参数传递。否则输出当前文本。
试试这个 XSLT
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:php="http://php.net/xsl"
version="1.0">
<xsl:output method="text" encoding="utf-8"/>
<xsl:template match="routes">
<xsl:apply-templates select="route"/>
</xsl:template>
<xsl:template match="route">
<xsl:apply-templates select="parameters"/>
</xsl:template>
<xsl:template match="parameters">
<xsl:apply-templates select="parameter[1]"/>
</xsl:template>
<xsl:template match="parameter">
<xsl:param name="text" select="string(./../../location)" />
<xsl:variable name="newText" select="php:function('str_replace', concat('', @name, ''), concat('(?<', @name, '>', text(), ')'), $text)"/>
<xsl:choose>
<xsl:when test="following-sibling::parameter">
<xsl:apply-templates select="following-sibling::parameter[1]">
<xsl:with-param name="text" select="$newText" />
</xsl:apply-templates>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$newText" />
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
注意,如果您可以使用 XSLT 2.0,您可以直接在 location
节点上使用 xsl:analyze-string
。
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output method="text" encoding="utf-8"/>
<xsl:key name="parameters" match="parameter" use="@name" />
<xsl:template match="routes">
<xsl:apply-templates select="route" />
</xsl:template>
<xsl:template match="route">
<xsl:variable name="root" select="/" />
<xsl:analyze-string select="location" regex="\([a-z]+)\">
<xsl:matching-substring>
<xsl:value-of select="key('parameters', regex-group(1), $root)" />
</xsl:matching-substring>
<xsl:non-matching-substring>
<xsl:value-of select="." />
</xsl:non-matching-substring>
</xsl:analyze-string>
</xsl:template>
</xsl:stylesheet>
【讨论】:
以上是关于XSL 中的递归替换的主要内容,如果未能解决你的问题,请参考以下文章