使用xslt替换xml节点

时间:2019-04-07 09:06:31

标签: java xml xslt

在此xml中,我想将<transfom>节点替换为另一个节点<message>,但复制数据。

xslt是否有可能,我已经使用xslt 2.0将转换节点转换为消息节点,但是它仅适用于一个流节点。

<root
    xmlns="http://www.example.com/something">
    <flow>
        <list name="listName"/>
        <router name="router"/>
        <!-- I have some other tags here -->
    </flow>
    <flow>
        <list name="listName"/>
        <console name="console"/>
        <!-- I have some other tags here -->
    </flow>
    <flow>
        <payload name="example"/>
        <transform name="transform">
            <!-- Some DATA here --->
        </transform>
        <!-- I have some other tags here -->
    </flow>
    <flow>
        <payload name="sada"/>
        <transform name="transform1">
            <!-- Some DATA here --->
        </transform>
        <!-- I have some other tags here -->
        <transform name="transform2">
            <!-- Some DATA here --->
        </transform>
    </flow>
</root>

<transform>节点存在于两个<flow>节点中。有没有什么方法可以编写通用XSLT,用<transform>节点替换<message>节点,从而保持节点的位置以及节点内部的数据。

我使用过<xsl:for-each><xsl:when>以及xpath表达式,例如previous,after。但是它们仅转换<transform name="transform node">,而照原样复制所有其他xml节点。请让我知道如何解决这个问题!


更新

这是我用于转换xml的样式表

<xsl:stylesheet version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <root>
        <xsl:for-each select="flow">
            <xsl:choose>
                <xsl:when test="descendant-or-self::transform">
                    <message>
                        <xsl:attribute name="doc:name">
                            <xsl:value-of
                                        select="//transform/@name" />
                        </xsl:attribute>
                        <ee:message>
                            <ee:set-payload>
                                <xsl:value-of select="payload" />
                            </ee:set-payload>
                        </ee:message>
                    </ee:transform>
                </xsl:when>
            </xsl:choose>
        </xsl:for-each>
    </root>
</xsl:stylesheet>

更新14/04/2019

如何从<root>标记更改命名空间?我有一堆要在转换时更改的名称空间。该怎么做?

1 个答案:

答案 0 :(得分:0)

转换设计应该从身份转换开始(请参见https://www.w3.org/TR/xslt20/#element-copy中的“示例:身份转换”部分),然后仅添加要转换的节点的模板,在XSLT 3中,您可以声明身份转换作为使用<xsl:mode on-no-match="shallow-copy"/>https://www.w3.org/TR/xslt-30/#built-in-templates-shallow-copy)的默认处理,然后您只需要为transform元素编写一个模板:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xpath-default-namespace="http://www.example.com/something"
    xmlns="http://www.example.com/something"
    exclude-result-prefixes="#all"
    version="3.0">

  <xsl:mode on-no-match="shallow-copy"/>

  <xsl:template match="flow/transform">
      <message>
          <xsl:apply-templates select="@*, node()"/>
      </message>
  </xsl:template>

</xsl:stylesheet>

https://xsltfiddle.liberty-development.net/pPzifpw

在XSLT 2中,您必须将其拼写清楚:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xpath-default-namespace="http://www.example.com/something"
    xmlns="http://www.example.com/something"
    exclude-result-prefixes="#all"
    version="2.0">

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

  <xsl:template match="flow/transform">
      <message>
          <xsl:apply-templates select="@*, node()"/>
      </message>
  </xsl:template>

</xsl:stylesheet>