我想基于输入文件表达式自动化元素。
我的输入文件类似于
<?xml version="1.0" encoding="UTF-8"?>
<mappings>
<mapping inputContext="InputRoot" outputContext="outputRoot">
<input>InputParent/InputChild/InputSubChild</input>
<output>OutputParent/OPChild</output>
</mapping>
</mappings>
基于上面的XML我创建了下面的XSLT
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns="http://www.testmapping.org/mapping">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/">
<xsl:variable name="outputCtxt" select="mappings/mapping/output"/>
<xsl:call-template name="contextGenerator">
<xsl:with-param name="contextPath" select="$outputCtxt"/>
</xsl:call-template>
</xsl:template>
<xsl:template name="contextGenerator">
<xsl:param name="contextPath" as="xs:string?"/>
<xsl:variable name="currentContext" select="substring-before($contextPath,'/')"/>
<xsl:variable name="subContext" select="substring-after($contextPath,'/')"/>
<xsl:element name="{$currentContext}">
<xsl:call-template name="contextGenerator">
<xsl:with-param name="contextPath" select="$subContext"/>
</xsl:call-template>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
我期待输出格式低于
<outputRoot>
<OutputParent>
<OPChild></OPChild>
</OutputParent>
</outputRoot>
当我尝试基于输入进行转换时,我最终会遇到预期的QName错误。我是否可以提出解决此问题的建议。
答案 0 :(得分:3)
contextGenerator
模板未正确拆分和递归。 (第二次调用时/
的参数中没有contextGenerator
,因此拆分失败。)
将以下内容添加到模板有助于显示问题:
<xsl:message>
[<xsl:value-of select="$currentContext"/>]
[<xsl:value-of select="$subContext"/>]
</xsl:message>
输出:
[OutputParent]
[OPChild]
[]
[]
以下替换模板会生成正确的输出:
<xsl:template name="contextGenerator">
<xsl:param name="contextPath" as="xs:string?"/>
<xsl:choose>
<xsl:when test="contains($contextPath, '/')">
<xsl:element name="{substring-before($contextPath, '/')}">
<xsl:variable name="subContext"
select="substring-after($contextPath, '/')"/>
<xsl:if test="$subContext">
<xsl:call-template name="contextGenerator">
<xsl:with-param name="contextPath" select="$subContext"/>
</xsl:call-template>
</xsl:if>
</xsl:element>
</xsl:when>
<xsl:otherwise>
<xsl:element name="{$contextPath}"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
结果:
<OutputParent>
<OPChild/>
</OutputParent>
答案 1 :(得分:1)
使用XSLT 2.0可以实现更简单,更简单,更高效的解决方案:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:my="my:my">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:variable name="vOutNames" select=
"tokenize(/*/*/output, '/')"/>
<xsl:template match="/">
<xsl:sequence select="my:gen($vOutNames)"/>
</xsl:template>
<xsl:function name="my:gen" as="element()?">
<xsl:param name="pNames" as="xs:string*"/>
<xsl:if test="$pNames[1]">
<xsl:element name="{$pNames[1]}">
<xsl:sequence select="my:gen($pNames[position() >1])"/>
</xsl:element>
</xsl:if>
</xsl:function>
</xsl:stylesheet>
将此转换应用于提供的XML文档:
<mappings>
<mapping inputContext="InputRoot" outputContext="outputRoot">
<input>InputParent/InputChild/InputSubChild</input>
<output>OutputParent/OPChild</output>
</mapping>
</mappings>
产生了想要的正确结果:
<OutputParent>
<OPChild/>
</OutputParent>
答案 2 :(得分:0)
在XML中,元素名称必须符合QNames的词法结构。您正在尝试创建名为InputParent/InputChild/InputSubChild
的元素。这包含QNames中不允许的字符(/
)。
要修正错误,您可以将_
替换为/
...取决于您的要求。
E.g。
<xsl:element name="{replace($currentContext, '/', '_')}">