XSLT按原样返回输入xml,除了将字符串替换为另一个字符串,无论它出现在何处

时间:2017-11-17 02:28:41

标签: xml xslt xpath

我的目标是生成一个与输入相同的XSLT输出,但将字符串替换为另一个字符串除外,无论它出现在何处。要替换的字符串可以是数据,xml标记名称,命名空间名称URI或xml文档中的任何其他内容,我希望它替换为任何一种方式。

示例xml输入:

<?xml version="1.0" encoding="utf-8"?>

<ns:a xmlns:ns="http://www.toreplace.com" xmlns:nsB="http://www.toreplace.com/anything">
  <nsB:b>
    toreplace
    <toreplace>
      data toreplace
    </toreplace>
    toreplace
  </nsB:b>
</ns:a>

期望的输出:

<?xml version="1.0" encoding="utf-8"?>

<ns:a xmlns:ns="http://www.replaceto.com" xmlns:nsB="http://www.replaceto.com/anything">
  <nsB:b>
    replaceto
    <replaceto>
      data replaceto
    </replaceto>
    replaceto
  </nsB:b>
</ns:a>

到目前为止我最好的尝试:

<?xml version="1.0" encoding="UTF-8"?>

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

<xsl:output omit-xml-declaration="no" indent="no"/>

<xsl:template match="*">
    <xsl:copy-of select="replace(., 'toreplace', 'replaceto')"/>
</xsl:template>

</xsl:stylesheet>

这会产生输出:

<?xml version="1.0" encoding="UTF-8"?>

    replaceto

      data replaceto

    replaceto

我遇到的问题是,由替换函数产生的输出省略了除数据之外的所有内容,即使相同的XPath表达式(点)在以下示例中没有省略任何内容:

<?xml version="1.0" encoding="UTF-8"?>

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

<xsl:output omit-xml-declaration="no" indent="no"/>

<xsl:template match="*">
    <xsl:copy-of select="."/>
</xsl:template>

</xsl:stylesheet>

产生

<?xml version="1.0" encoding="UTF-8"?>
<ns:a xmlns:ns="http://www.toreplace.com" xmlns:nsB="http://www.toreplace.com/anything">
  <nsB:b>
    toreplace
    <toreplace>
      data toreplace
    </toreplace>
    toreplace
  </nsB:b>
</ns:a>

是什么导致看似相同的XPath表达式的不同行为?我该如何解决这个问题?我是否需要一种完全不同的方法来实现我的目标?

1 个答案:

答案 0 :(得分:1)

您可以使用:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="2.0">

    <!--Template to change namespace -->
    <xsl:template match="*[namespace-uri()[matches(., 'toreplace')]]" priority="1">
        <xsl:element name="{replace(name(), 'toreplace', 'replaceto')}" namespace="{replace(namespace-uri(), 'toreplace', 'replaceto')}">
            <xsl:apply-templates select="node()|@*"></xsl:apply-templates>
        </xsl:element>
    </xsl:template>

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

    <!--Template for Text Change -->
    <xsl:template match="text()[matches(., 'toreplace')]">
        <xsl:value-of select="replace(., 'toreplace', 'replaceto')"/>
    </xsl:template>

    <!--Template for Element name Change -->
    <xsl:template match="*[matches(local-name(), 'toreplace')]">
        <xsl:element name="{replace(local-name(), 'toreplace', 'replaceto')}">
            <xsl:apply-templates select="node()|@*"></xsl:apply-templates>
        </xsl:element> 
    </xsl:template>

    <!--Template for Attribute Name and Value Change -->
    <xsl:template match="@*[matches(., 'toreplace') or matches(name(), 'toreplace')]">
        <xsl:attribute name="{replace(local-name(), 'toreplace', 'replaceto')}">
            <xsl:value-of select="replace(., 'toreplace', 'replaceto')"/>
        </xsl:attribute>
    </xsl:template>

</xsl:stylesheet>

<强>输出

<ns:a xmlns:ns="http://www.replaceto.com">
    <nsB:b xmlns:nsB="http://www.toreplace.com/anything">
        replaceto
        <replaceto>
            data replaceto
        </replaceto>
        replaceto
    </nsB:b>
</ns:a>