使用XSLT 2.0动态替换XML中的属性或元素值

时间:2017-10-03 20:08:16

标签: xml xslt-2.0

我有一个XML

<?xml version="1.0" encoding="utf-8"?>
<CATALOG>
    <PLANT COLOR="@DYNAMIC_COLOR@">
        <COMMON>Bloodroot</COMMON>
        <BOTANICAL>Sanguinaria canadensis</BOTANICAL>
        <ZONE>4</ZONE>
        <LIGHT>Mostly Shady</LIGHT>
        <PRICE>@DYNAMIC_PRICE@</PRICE>
        <AVAILABILITY>031599</AVAILABILITY>
    </PLANT>
    <PLANT COLOR="RED" TYPE="@DYNAMIC_TYPE@">
        <COMMON>Columbine</COMMON>
        <BOTANICAL>Aquilegia canadensis</BOTANICAL>
        <ZONE>3</ZONE>
        <LIGHT>Mostly Shady</LIGHT>
        <PRICE>$9.37</PRICE>
        <AVAILABILITY>030699</AVAILABILITY>
    </PLANT>
</CATALOG>

我想转型为

<?xml version="1.0" encoding="utf-8"?>
<CATALOG>
    <PLANT COLOR="RED">
        <COMMON>Bloodroot</COMMON>
        <BOTANICAL>Sanguinaria canadensis</BOTANICAL>
        <ZONE>4</ZONE>
        <LIGHT>Mostly Shady</LIGHT>
        <PRICE>10</PRICE>
        <AVAILABILITY>031599</AVAILABILITY>
    </PLANT>
    <PLANT COLOR="RED" TYPE="HERBS">
        <COMMON>Columbine</COMMON>
        <BOTANICAL>Aquilegia canadensis</BOTANICAL>
        <ZONE>3</ZONE>
        <LIGHT>Mostly Shady</LIGHT>
        <PRICE>$9.37</PRICE>
        <AVAILABILITY>030699</AVAILABILITY>
    </PLANT>
</CATALOG>

基本上,我想替换&#34; @DYNAMIC _ * @&#34;具有预定义值的属性/元素值。请帮忙!!!我可以为每个人做,并准确找到值,并用所需的值替换它。但我更喜欢使用应用模板概念。

1 个答案:

答案 0 :(得分:0)

解决此类问题的一个简洁方法是将骨架XML文档转换为样式表。编写一个转换,将其转换为:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="3.0" expand-text="yes">
  <xsl:param name="DYNAMIC_COLOR"/>
  <xsl:param name="DYNAMIC_TYPE"/>
  <xsl:template name="xsl:initial-template">
<CATALOG>
    <PLANT COLOR="{$DYNAMIC_COLOR}">
        <COMMON>Bloodroot</COMMON>
        <BOTANICAL>Sanguinaria canadensis</BOTANICAL>
        <ZONE>4</ZONE>
        <LIGHT>Mostly Shady</LIGHT>
        <PRICE>{$DYNAMIC_PRICE}</PRICE>
        <AVAILABILITY>031599</AVAILABILITY>
    </PLANT>
    <PLANT COLOR="RED" TYPE="{$DYNAMIC_TYPE}">
        <COMMON>Columbine</COMMON>
        <BOTANICAL>Aquilegia canadensis</BOTANICAL>
        <ZONE>3</ZONE>
        <LIGHT>Mostly Shady</LIGHT>
        <PRICE>$9.37</PRICE>
        <AVAILABILITY>030699</AVAILABILITY>
    </PLANT>
</CATALOG>
  </xsl:template>
</xsl:stylesheet>

然后使用入口点“xsl:initial-template”和参数值执行此样式表。我在这里使用了XSLT 3.0值模板,使它更容易一些;如果你想使用XSLT 2.0,你可以生成xsl:value-of instructions。

转换的基本逻辑是

<xsl:stylesheet ...>
<xsl:namespace-alias stylesheet-prefix="z" result-prefix="xsl"/>
<xsl:variable name="params" select="distinct-values(
     (//@*|//text())[matches(., '^@.*@^')]!translate(., '@', ''))"/>

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

<xsl:template match="/">
  <z:stylesheet version="3.0" expand-text="yes">
    <xsl:for-each select="$params">
      <z:param name="{.}"/>
    </xsl:for-each>
    <z:template name="xsl:initial-template">          
      <xsl:apply-templates/>
    </z:template>
  </z:stylesheet>
</xsl:template>

<xsl:template match="@*[matches(., '^@.*@$')]">
  <xsl:attribute name="{name()}" select="replace(., '^@(.*)@$', '{\$$1}')"/>
</xsl:template>

<xsl:template match="text()[matches(., '^@.*@$')]">
  <!-- 3.0 -->
  <!-- <xsl:value-of select="replace(., '^@(.*)@$', '{\$$1}')"/> -->
  <!-- 2.0 -->
  <z:value-of select="replace(., '^@(.*)@$', '\$$1'"/>
</xsl:template>

</xsl:stylesheet>

如果存在包含花括号的属性或文本节点,则可能需要做更多工作:这些需要加倍。