在XSLT中将节点添加到另一个节点

时间:2009-10-09 03:22:33

标签: xml xslt

我有这样的xml:

  <configurationData>
    <path name='b'>
      <path name='a'>
        <setting name='s1'>
        ![CDATA[XXXX]]
        </setting>
        <setting name='s2'>
          XXXX
        </setting>
      </path>
    </path>
  </configurationData>

其中configurationData是根节点,并且可能存在嵌套路径,后跟一个或多个设置节点。我想转换设置节点以将设置节点的内容放入名为value

的子节点
  <configurationData>
    <path name='b'>
      <path name='a'>
        <setting name='s1'>
          <value>![CDATA[XXXX]]</value>
        </setting>
        <setting name='s2'>
          <value>XXXX</value>
        </setting>
      </path>
    </path>
  </configurationData>

我必须承认我发现XML是一个心理障碍,我看不出要使用的XSLT:

这是我的尝试:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:output encoding ="utf-8" indent="yes" method="xml" version="1.0"/>

  <xsl:template match='/setting'>
    <xsl:apply-templates select='setting' />
  </xsl:template>

  <xsl:template match='setting'>
    <value>
      <xsl:value-of select='.'/>
    </value>
  </xsl:template>
</xsl:stylesheet>

2 个答案:

答案 0 :(得分:3)

你有90%的路要走。你需要的是“身份模板”

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:output encoding ="utf-8" indent="yes" method="xml" version="1.0"/>

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

    <xsl:template match='setting'>
        <xsl:copy>
            <xsl:apply-templates select="@*"/>
            <value>
                <xsl:value-of select='.'/>
            </value>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

第一个模板处理所有节点,将它们复制到输出。但是,更具体的“设置”模板会被“设置”节点调用,该模板会复制节点本身及其属性,然后将值包装在“值”标记中。

关于XSLT最不具有启发性的是样式表不是驱动该过程的程序。相反,它是控制的输入XML文档,样式表提供了根据输入中的内容选择和执行的指令。这称为“推”处理。 XSL处理器将数据推送到样式表。 XSLT确实有一些程序功能,你可以用“拉”样式编写一个样式表,样式表试图驱动这个过程,但这样做更难,导致难以维护的样式表。

编辑: 要启用CDATA部分,请替换:

<xsl:value-of select='.' />

![CDATA[<xsl:value-of select='.' disable-output-escaping="yes"/>]]

(虽然不是最好的解决方案,因为它总是把CDATA放进去)

答案 1 :(得分:0)

我的建议,基于吉姆加里森的回答:

<xsl:stylesheet 
  version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>
  <xsl:output method="xml" encoding="utf-8" cdata-section-elements="value" />

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

  <xsl:template match="setting/text()">
    <value>
      <xsl:value-of select="." />
    </value>
  </xsl:template>

</xsl:stylesheet>