xsl模板用自定义字符替换字符串的每个字符

时间:2018-02-07 09:42:22

标签: xml xslt transformation

我有一个用例,我想用自定义字符转换xml键值,该自定义字符等于值的长度。我要转换的Xml请求是:

<root>
    <entries>
        <entry>
            <key>key1</key>
            <value>value1</value>
        </entry>
        <entry>
            <key>key2</key>
            <value>value2</value>
        </entry>
        <entry>
            <key>key3</key>
            <value>value3</value>
        </entry>
    </entries>
</root>

我用于将特定键值转换为自定义值的当前xml模板,如 Looking for a utility to mask xml content in form of key value tags

中所述

现在我不想要静态3#字符作为我的替换值。我不想要。 hash的值等于key的值。

1 个答案:

答案 0 :(得分:0)

如果您使用的是XSLT 2.0或更高版本,则可以使用replace() ...

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output indent="yes"/>
  <xsl:strip-space elements="*"/>

  <xsl:param name="keys" select="'key1','key2','key3'"/>
  <xsl:param name="char" select="'#'"/>

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

  <xsl:template match="entry[key=$keys]/value/text()">
    <xsl:value-of select="replace(.,'.',$char)"/>
  </xsl:template>

</xsl:stylesheet>

如果您使用的是XSLT 1.0,则可以使用带有长第三个参数的translate()。这有点像hacky,并且只会处理值,只要第三个参数......

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output indent="yes"/>
  <xsl:strip-space elements="*"/>

  <xsl:param name="keys" select="'|key1|key2|key3|'"/>
  <xsl:param name="mask" 
    select="'###################################################################'"/>

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

  <xsl:template match="value/text()">
    <xsl:choose>
      <xsl:when test="contains($keys,concat('|',../../key,'|'))">
        <xsl:value-of select="translate(.,.,$mask)"/>        
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="."/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

</xsl:stylesheet>

更好的XSLT 1.0选项是使用递归模板调用...

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output indent="yes"/>
  <xsl:strip-space elements="*"/>

  <xsl:param name="keys" select="'|key1|key2|key3|'"/>
  <xsl:param name="char" select="'#'"/>

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

  <xsl:template match="value/text()" name="mask">
    <xsl:param name="input" select="."/>
    <xsl:variable name="toMask" select="substring($input,2)"/>
    <xsl:choose>
      <xsl:when test="contains($keys,concat('|',../../key,'|'))">
        <xsl:value-of select="$char"/>
        <xsl:if test="string($toMask)">
          <xsl:call-template name="mask">
            <xsl:with-param name="input" select="$toMask"/>
          </xsl:call-template>
        </xsl:if>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="."/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

</xsl:stylesheet>

所有这三个样式表,使用此输入:

<root>
    <entries>
        <entry>
            <key>key1</key>
            <value>value1</value>
        </entry>
        <entry>
            <key>key2</key>
            <value>value222222</value>
        </entry>
        <entry>
            <key>key3</key>
            <value></value>
        </entry>
        <entry>
            <key>key4</key>
            <value>leave me alone</value>
        </entry>        
    </entries>
</root>

将输出:

<root>
   <entries>
      <entry>
         <key>key1</key>
         <value>######</value>
      </entry>
      <entry>
         <key>key2</key>
         <value>###########</value>
      </entry>
      <entry>
         <key>key3</key>
         <value/>
      </entry>
      <entry>
         <key>key4</key>
         <value>leave me alone</value>
      </entry>
   </entries>
</root>