我正在寻找一些帮助,以使用XSLT将以下格式的XML转换为所需的输出-
输入XML:
<properties>
<entry>
<key>first_node</key>
<value>GDP</value>
</entry>
<entry>
<key>parent_node/second_node/third_node</key>
<value>INR</value>
</entry>
<entry>
<key>fourth_node</key>
<value>
<genericData>
<identifier>fourth_node</identifier>
<properties>
<entry>
<key>fifth_node/sixth_node</key>
<value>USD</value>
</entry>
<entry>
<key>seventh_node</key>
<value>EUR</value>
</entry>
</properties>
</genericData>
</value>
</entry>
<entry>
<key>eigth_node</key>
<value>
<genericData>
<identifier>eigth_node</identifier>
<properties>
<entry>
<key>ninth_node</key>
<value>SGD</value>
</entry>
<entry>
<key>tenth_node</key>
<value>PSO</value>
</entry>
</properties>
</genericData>
</value>
</entry>
</properties>
所需的输出:
<properties>
<first_node>GDP</first_node>
<parent_node>
<second_node>
<third_node>INR</third_node>
</second_node>
</parent_node>
<fourth_node>
<fifth_node>
<sixth_node>USD</sixth_node>
</fifth_node>
<seventh_node>EUR</seventh_node>
</fourth_node>
<eight_node>
<ninth_node>SGD</ninth_node>
<tenth_node>PSO</tenth_node>
</eight_node>
</properties>
我用可能的输入XML修改了这个问题,其中的格式稍有改变。
请提供有关XSLT版本1的帮助,以获取所需的输出。
非常感谢您的帮助。
答案 0 :(得分:1)
在XSLT 1.0中,如果您不能使用任何扩展功能,则可以通过使用递归命名模板来分割路径来实现它
尝试使用此XSLT
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="entry">
<xsl:call-template name="splitter">
<xsl:with-param name="path" select="key" />
<xsl:with-param name="value" select="value" />
</xsl:call-template>
</xsl:template>
<xsl:template name="splitter">
<xsl:param name="path" />
<xsl:param name="value" />
<xsl:choose>
<xsl:when test="contains($path, '/')">
<xsl:element name="{substring-before($path, '/')}">
<xsl:call-template name="splitter">
<xsl:with-param name="path" select="substring-after($path, '/')" />
<xsl:with-param name="value" select="$value" />
</xsl:call-template>
</xsl:element>
</xsl:when>
<xsl:otherwise>
<xsl:element name="{$path}">
<xsl:choose>
<xsl:when test=".//entry">
<xsl:apply-templates select=".//entry" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$value" />
</xsl:otherwise>
</xsl:choose>
</xsl:element>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
答案 1 :(得分:0)
在XSLT 2或3中,您可以使用XPath tokenize
函数在递归模板中构造具有元素名称的字符串序列,并根据需要构造嵌套元素:
<xsl:template match="entry">
<xsl:param name="element-names" as="xs:string*" select="tokenize(string[1], '/')"/>
<xsl:variable name="element-name" as="xs:string?" select="head($element-names)"/>
<xsl:choose>
<xsl:when test="$element-name">
<xsl:element name="{$element-name}">
<xsl:apply-templates select=".">
<xsl:with-param name="element-names" select="tail($element-names)"/>
</xsl:apply-templates>
</xsl:element>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="string[2]"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
完整的XSLT 3样式表应为
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="#all"
version="3.0">
<xsl:mode on-no-match="shallow-copy"/>
<xsl:output method="xml" indent="yes"/>
<xsl:template match="entry">
<xsl:param name="element-names" as="xs:string*" select="tokenize(string[1], '/')"/>
<xsl:variable name="element-name" as="xs:string?" select="head($element-names)"/>
<xsl:choose>
<xsl:when test="$element-name">
<xsl:element name="{$element-name}">
<xsl:apply-templates select=".">
<xsl:with-param name="element-names" select="tail($element-names)"/>
</xsl:apply-templates>
</xsl:element>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="string[2]"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
在https://xsltfiddle.liberty-development.net/3NzcBtK的示例中,对于XSLT 2,您需要阐明身份转换,并且我认为代替head($element-names)
而不是element-names[1]
而不是{{ 1}}调用该变量,您将需要tail
。