我在尝试解决我面临的问题时遇到了很多困难。我们有一个源XML Schema,我们正在使用XSLT转换为Target Schema。但是,目标模式中的一个元素旨在保存源XML(包括属性)中的原始XML。我不希望使用CDATA,因为这会在再次使用数据时导致问题。我在BizTalk 2009中运行这个XSLT所以我将仅限于使用XSLT 1.0 / XPATH 1.0。
哦,为了使事情进一步复杂化,源XML中的数据具有<和>在一些元素中。
来源示例:
<root>
<foo company="1">
<bar id="125" title="foobar3">
> 15 years
</bar>
<bar id="126" title="foobar4">
< 5 years
</bar>
</foo>
<foo company="2">
<bar id="125" title="foobar3">
> 15 years
</bar>
<bar id="126" title="foobar4">
< 5 years
</bar>
</foo>
示例目标
<newXML>
<Company>1</Company>
<SourceXML>
<root>
<foo company="1">
<bar id="125" title="foobar3">
">" 15 years
</bar>
<bar id="126" title="foobar4">
"<" 5 years
</bar>
</foo>
<foo company="2">
<bar id="125" title="foobar3">
">" 15 years
</bar>
<bar id="126" title="foobar4">
"<" 5 years
</bar>
</foo>
</root>
</SourceXML>
</newXML>
答案 0 :(得分:1)
这并不复杂。您只需要为元素和属性节点编写两个模板,将所需的文本表示写入输出树。只有文本节点中带引号的<
和>
的包装需要更多的输入。样式表看起来像这样:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<newXML>
<Company>1</Company>
<SourceXML>
<xsl:apply-templates/>
</SourceXML>
</newXML>
</xsl:template>
<xsl:template match="*">
<xsl:value-of select="concat('<',name())"/>
<xsl:apply-templates select="@*"/>
<xsl:text>></xsl:text>
<xsl:apply-templates select="node()"/>
<xsl:value-of select="concat('</',name(), '>')"/>
</xsl:template>
<xsl:template match="@*">
<xsl:value-of select="concat(' ', name(),'=','"', ., '"')"/>
</xsl:template>
<xsl:template match="text()">
<xsl:call-template name="wrap">
<xsl:with-param name="str">
<xsl:call-template name="wrap">
<xsl:with-param name="str" select="."/>
<xsl:with-param name="find" select="'<'"/>
</xsl:call-template>
</xsl:with-param>
<xsl:with-param name="find" select="'>'"/>
</xsl:call-template>
</xsl:template>
<xsl:template name="wrap">
<xsl:param name="str"/>
<xsl:param name="find"/>
<xsl:choose>
<xsl:when test="contains($str, $find)">
<xsl:variable name="before" select="substring-before($str, $find)"/>
<xsl:variable name="after" select="substring-after($str, $find)"/>
<xsl:value-of select="concat($before, '"', $find, '"')"/>
<xsl:call-template name="wrap">
<xsl:with-param name="str" select="$after"/>
<xsl:with-param name="find" select="$find"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$str"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>