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

xsl template to replace each character of string with a custom character

我有一个用例,我想用等于值长度的自定义字符转换 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 模板如

中所建议

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

如果您使用 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()。不过,这有点老套,并且只会处理与第三个参数一样长的值...

<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>