2017-10-28 161 views
0

任何指导我可以根据令牌将给定的xml元素值拆分为多个子元素。这里是我的示例输入xml和所需的输出。我有使用xsl 1.0的限制。谢谢。字符串使用XSL 1.0拆分为新元素

输入XML:

<?xml version='1.0' encoding='UTF-8'?> 
<SQLResults> 
    <SQLResult> 
     <ACTION1>Action1</ACTION1> 
     <ACTION2>Action2</ACTION2> 
     <Encrypt>Program=GPG;Code=23FCS;</Encrypt> 
     <SENDER>Program=WebPost;Protocol=WS;Path=/home/Inbound</SENDER> 
    </SQLResult> 
</SQLResults> 

输出XML:

<?xml version='1.0' encoding='UTF-8'?> 
<SQLResults> 
    <SQLResult> 
     <ACTION1>Action1</ACTION1> 
     <ACTION2>Action2</ACTION2> 
     <Encrypt> 
      <Program>GPG</Program> 
      <Code>23FCS</Code> 
     </Encrypt> 
     <SENDER> 
      <Program>Action4</Program> 
      <Protocol>WS</Protocol> 
      <Path>/home/Inbound</Path> 
     </SENDER> 
    </SQLResult> 
</SQLResults> 
+0

嗯,首先检查是否您的XSLT 1.0处理器不支持http://exslt.org/str/functions/tokenize/index.html,如果不,您仍然可以使用基于XSLT 1.0模板的实现http://exslt.org/str/functions/tokenize/str.tokenize.template.xsl。 –

+0

谢谢。我正在检查。感谢您能否指出我具有上述功能的片段。 – GSR

回答

1

XSLT 2它会很容易,只需用下面的模板:

<xsl:template match="Encrypt|SENDER"> 
    <xsl:copy> 
    <xsl:analyze-string select="." regex="(\w+)=([\w/]+);?"> 
     <xsl:matching-substring> 
     <element name="{regex-group(1)}"> 
      <xsl:value-of select="regex-group(2)"/> 
     </element> 
     </xsl:matching-substring> 
    </xsl:analyze-string> 
    </xsl:copy> 
</xsl:template> 

因为你w ^蚂蚁在XSLT 1这样做,你必须用另一种方式来表达。

而不是analyze-string你必须:

  • 令牌化内容为包含;字符之间的非空令牌。 您必须添加tokenize模板。
  • 每个这样的标记分成2个子字符串,在= char之前和之后。
  • 创建一个名称与第一个子字符串相同的元素。
  • 编写此元素的内容 - 第二个子字符串。

XSLT 1也有这样的限制,即tokenize模板 的结果是一个结果树片段(RTF)不是节点设置,因此它不能在XPath表达式中使用 。

要规避此限制,您必须使用exsl:node-set函数。

所以整个脚本看上去象下面这样:

<?xml version="1.0" encoding="UTF-8" ?> 
<xsl:transform version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:exsl="http://exslt.org/common"> 
    <xsl:output method="xml" encoding="UTF-8" indent="yes" /> 
    <xsl:strip-space elements="*"/> 

    <xsl:template match="Encrypt|SENDER"> 
    <xsl:copy> 
     <xsl:variable name="tokens"> 
     <xsl:call-template name="tokenize"> 
      <xsl:with-param name="txt" select="."/> 
      <xsl:with-param name="delim" select="';'"/> 
     </xsl:call-template> 
     </xsl:variable> 
     <xsl:for-each select="exsl:node-set($tokens)/token"> 
     <xsl:variable name="t1" select="substring-before(., '=')"/> 
     <xsl:variable name="t2" select="substring-after(., '=')"/> 
     <xsl:element name="{$t1}"> 
      <xsl:value-of select="$t2" /> 
     </xsl:element> 
     </xsl:for-each> 
    </xsl:copy> 
    </xsl:template> 

    <xsl:template name="tokenize"> 
    <xsl:param name="txt" /> 
    <xsl:param name="delim" select="' '" /> 
    <xsl:choose> 
     <xsl:when test="$delim and contains($txt, $delim)"> 
     <token> 
      <xsl:value-of select="substring-before($txt, $delim)" /> 
     </token> 
     <xsl:call-template name="tokenize"> 
      <xsl:with-param name="txt" select="substring-after($txt, $delim)" /> 
      <xsl:with-param name="delim" select="$delim" /> 
     </xsl:call-template> 
     </xsl:when> 
     <xsl:when test="$txt"> 
     <token><xsl:value-of select="$txt" /></token> 
     </xsl:when> 
    </xsl:choose> 
    </xsl:template> 

    <xsl:template match="@*|node()"> 
    <xsl:copy><xsl:apply-templates select="@*|node()"/></xsl:copy> 
    </xsl:template> 
</xsl:transform> 
+0

非常感谢您的解释。这是我的工作。再次感谢你。 – GSR