xslt转换xml元素中的xml字符串
这是一个棘手的问题 我有以下XMLxslt转换xml元素中的xml字符串,xslt,Xslt,这是一个棘手的问题 我有以下XML <test> <testElement SomeAttribute="<otherxml><otherElement>test test</otherElement></otherxml>"> </testElement> </test> 使用XSLT,我希望将此XML转换为以下结果 <test> <testE
<test>
<testElement SomeAttribute="<otherxml><otherElement>test test</otherElement></otherxml>">
</testElement>
</test>
使用XSLT,我希望将此XML转换为以下结果
<test>
<testElement>
<SomeAttributeTransformedToElement>
<otherxml>
<otherElement>test test</otherElement>
</otherxml>
</SomeAttributeTransformedToElement>
</testElement>
</test>
测试
基本上,属性中的某些文本必须转换为最终XML中的实际元素
如何在XSLT中实现这一点
Alex您可以通过禁用输出转义来实现这一点。但是,请注意,您的输入文档不是有效的XML文档(
XSLT
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="@SomeAttribute">
<SomeAttributeTransformedToElement>
<xsl:value-of select="." disable-output-escaping="yes"/>
</SomeAttributeTransformedToElement>
</xsl:template>
</xsl:stylesheet>
请注意,使用
disable output escaping=“yes”
不再保证生成的输出文档是格式良好的XML文档。我也有同样的需求,我最终成功地构建了一些工作
然而,这还远远不够完美。但是,由于这个解决方案对我很有效(在我的案例中非常有用),我将它提供给任何可能被询问的人
我希望XSL纯粹主义者会原谅我这样做:
此XSLT命名模板将文本变量作为输入,并在输出上生成XML元素。
警告:存在一些限制:
- XML不能有自包含的元素(…被禁止,因为“a”元素包含另一个“a”)
- XML必须规范化(元素名和属性之间只有一个空格,所以是允许的,但不允许(这是可以修复的)
- <element/>样式尚未处理(很抱歉,我不需要它,而且我正在忙于当前的项目),但这很容易修复
<xsl:template name="t-convert">
<xsl:param name="TEXT"/>
<xsl:choose>
<xsl:when test="starts-with($TEXT,'<?')">
<xsl:call-template name="t-convert">
<xsl:with-param name="TEXT" select="substring-after($TEXT,'?>')"/>
</xsl:call-template>
</xsl:when>
<!-- Si le texte contient encore des elements -->
<xsl:when test="contains($TEXT,'<')">
<xsl:variable name="before-first-open" select="substring-before($TEXT,'<')"/>
<xsl:variable name="after-first-open" select="substring-after($TEXT,'<')"/>
<!-- On ecrit le texte qui précéde l'élément -->
<xsl:value-of select="$before-first-open"/>
<!-- Le nom de l'élément -->
<xsl:variable name="TRAD" select="translate($after-first-open,'>',' ')"/>
<!-- TODO : Gere le cas <ELEMENT /> -->
<xsl:variable name="ELEMENT" select="substring-before($TRAD,' ')"/>
<xsl:variable name="suite" select="substring-after($after-first-open,$ELEMENT)"/>
<xsl:variable name="DEFINITION" select="substring-before($suite,'>')"/>
<xsl:variable name="CONTENT" select="substring-after(substring-before($suite,concat('</',$ELEMENT)),concat($DEFINITION,'>'))"/>
<xsl:variable name="FOLLOWING">
<xsl:choose>
<xsl:when test="substring($DEFINITION,string-length($DEFINITION))='/'"><!-- ends-with($DEFINITION,'/') not compatible with all XSLT version -->
<xsl:value-of select="substring-after($suite,'/>')"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="substring-after(substring-after($suite,concat('</',$ELEMENT)),'>')"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:element name="{$ELEMENT}">
<xsl:call-template name="t-attribs">
<xsl:with-param name="TEXT" select="$DEFINITION"/>
</xsl:call-template>
<xsl:call-template name="t-convert">
<xsl:with-param name="TEXT" select="$CONTENT"/>
</xsl:call-template>
</xsl:element>
<xsl:call-template name="t-convert">
<xsl:with-param name="TEXT" select="$FOLLOWING"/>
</xsl:call-template>
</xsl:when>
<!-- no more element -->
<xsl:otherwise>
<xsl:value-of select="$TEXT"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="t-attribs">
<xsl:param name="TEXT"/>
<xsl:if test="contains($TEXT,'=')">
<!-- Assert TEXT=' NAME="VALUE".*' -->
<xsl:variable name="NAME" select="substring-after(substring-before($TEXT,'='),' ')"/>
<xsl:variable name="afterName" select="substring-after($TEXT,'="')"/>
<xsl:variable name="VALUE" select="substring-before($afterName,'"')"/>
<xsl:variable name="FOLLOWING" select="substring-after($afterName,'"')"/>
<xsl:attribute name="{$NAME}">
<xsl:value-of select="$VALUE"/>
</xsl:attribute>
<xsl:call-template name="t-attribs">
<xsl:with-param name="TEXT" select="FOLLOWING"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
好的,我知道,但是你明白了。属性中的字符串实际上是转义的:otherxml>otherElement>test/otherElement>/otherxml>+1正确答案。除此之外,只有一个解析器。而且,到目前为止,不需要这样的编码字符串,因为每个主要的数据库引擎都正确地支持XML。
<xsl:template name="t-convert">
<xsl:param name="TEXT"/>
<xsl:choose>
<xsl:when test="starts-with($TEXT,'<?')">
<xsl:call-template name="t-convert">
<xsl:with-param name="TEXT" select="substring-after($TEXT,'?>')"/>
</xsl:call-template>
</xsl:when>
<!-- Si le texte contient encore des elements -->
<xsl:when test="contains($TEXT,'<')">
<xsl:variable name="before-first-open" select="substring-before($TEXT,'<')"/>
<xsl:variable name="after-first-open" select="substring-after($TEXT,'<')"/>
<!-- On ecrit le texte qui précéde l'élément -->
<xsl:value-of select="$before-first-open"/>
<!-- Le nom de l'élément -->
<xsl:variable name="TRAD" select="translate($after-first-open,'>',' ')"/>
<!-- TODO : Gere le cas <ELEMENT /> -->
<xsl:variable name="ELEMENT" select="substring-before($TRAD,' ')"/>
<xsl:variable name="suite" select="substring-after($after-first-open,$ELEMENT)"/>
<xsl:variable name="DEFINITION" select="substring-before($suite,'>')"/>
<xsl:variable name="CONTENT" select="substring-after(substring-before($suite,concat('</',$ELEMENT)),concat($DEFINITION,'>'))"/>
<xsl:variable name="FOLLOWING">
<xsl:choose>
<xsl:when test="substring($DEFINITION,string-length($DEFINITION))='/'"><!-- ends-with($DEFINITION,'/') not compatible with all XSLT version -->
<xsl:value-of select="substring-after($suite,'/>')"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="substring-after(substring-after($suite,concat('</',$ELEMENT)),'>')"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:element name="{$ELEMENT}">
<xsl:call-template name="t-attribs">
<xsl:with-param name="TEXT" select="$DEFINITION"/>
</xsl:call-template>
<xsl:call-template name="t-convert">
<xsl:with-param name="TEXT" select="$CONTENT"/>
</xsl:call-template>
</xsl:element>
<xsl:call-template name="t-convert">
<xsl:with-param name="TEXT" select="$FOLLOWING"/>
</xsl:call-template>
</xsl:when>
<!-- no more element -->
<xsl:otherwise>
<xsl:value-of select="$TEXT"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="t-attribs">
<xsl:param name="TEXT"/>
<xsl:if test="contains($TEXT,'=')">
<!-- Assert TEXT=' NAME="VALUE".*' -->
<xsl:variable name="NAME" select="substring-after(substring-before($TEXT,'='),' ')"/>
<xsl:variable name="afterName" select="substring-after($TEXT,'="')"/>
<xsl:variable name="VALUE" select="substring-before($afterName,'"')"/>
<xsl:variable name="FOLLOWING" select="substring-after($afterName,'"')"/>
<xsl:attribute name="{$NAME}">
<xsl:value-of select="$VALUE"/>
</xsl:attribute>
<xsl:call-template name="t-attribs">
<xsl:with-param name="TEXT" select="FOLLOWING"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
<xsl:call-template name="t-convert">
<xsl:with-param name="TEXT" select="//content"/>
</xsl:call-template>