XSL在转换字符串中多次替换

时间:2018-11-29 13:59:40

标签: xml xslt xslt-1.0

我正在尝试将属性转换为节点并替换值以更正一个。转换和联接效果很好,但是我不知道如何替换转换后的数据。我尝试了choose并遍历属性没有任何结果。

这是源XML

<cats>
  <cat id="11">Foo 1</cat>
  <cat id="12">Foo 2</cat>
</cats>

我的XLS-此部分有效

<xsl:template match="cats">
    <cat-id>
       <xsl:value-of select="string-join(cat/@id, ',')" />
     </cat-id>
</xsl:template>

替换表11 => 24, 12 => 75, 13 => 145 ...

我想要实现的结果

<cat-id>24,75</cat-id>

2 个答案:

答案 0 :(得分:0)

您可以编写一个将每个id属性值映射到其替换的函数,在XSLT 3(自2017年以来由Saxon 9.8和更高版本以及Altova 2017和更高版本支持)中,您可以使用map作为函数:< / p>

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

    <xsl:param name="replacement-map" as="map(xs:integer, xs:integer)" select="map { 11 : 24, 12 : 75, 13 : 145 }"/>

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

    <xsl:template match="cats">
        <cat-id>
           <xsl:value-of select="cat/@id/$replacement-map(xs:integer(.))" separator="," />
         </cat-id>
    </xsl:template>

</xsl:stylesheet>

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

在XSLT 2中,您可以使用XML结构表示替换表/映射,并使用键来查找属性值的替换:

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

    <xsl:param name="replacement-map">
        <value key="11">24</value>
        <value key="12">75</value>
        <value key="13">145</value>
    </xsl:param>

    <xsl:key name="rep" match="value" use="@key"/>

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

    <xsl:template match="cats">
        <cat-id>
           <xsl:value-of select="cat/@id/key('rep', ., $replacement-map)" separator="," />
         </cat-id>
    </xsl:template>

</xsl:stylesheet>

https://xsltfiddle.liberty-development.net/jyH9rNs/1

最后在XSLT 1中,由于key函数没有第三个参数来更改上下文文档,因此可以使用

<xsl:stylesheet
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:exsl="http://exslt.org/common"
    xmlns:msxml="urn:schemas-microsoft-com:xslt"
    exclude-result-prefixes="exsl msxml"
    version="1.0">

  <xsl:param name="replacement-map-rtf">
    <value key="11">24</value>
    <value key="12">75</value>
    <value key="13">145</value>
  </xsl:param>

  <xsl:param name="replacement-map" select="exsl:node-set($replacement-map-rtf)"/>

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

  <xsl:key name="rep" match="value" use="@key"/>

  <xsl:template match="cats">
      <cat-id>
          <xsl:apply-templates select="cat/@id"/>
      </cat-id>
  </xsl:template>

  <xsl:template match="cat/@id">
      <xsl:if test="position() > 1">,</xsl:if>
      <xsl:variable name="this" select="."/>
      <xsl:for-each select="$replacement-map">
          <xsl:value-of select="key('rep', $this)"/>
      </xsl:for-each>
  </xsl:template>

</xsl:stylesheet>

https://xsltfiddle.liberty-development.net/jyH9rNs/2

答案 1 :(得分:0)

您可以在 XSLT 1.0 中做到这一点:

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:my="http://www.example.com/my"
exclude-result-prefixes="my">
<xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<my:replacement-map>
    <value key="11">24</value>
    <value key="12">75</value>
    <value key="13">145</value>
</my:replacement-map>

<xsl:template match="cats">
    <cat-id>
        <xsl:for-each select="cat">
            <xsl:value-of select="document('')/xsl:stylesheet/my:replacement-map/value[@key=current()/@id]" />
            <xsl:if test="position() != last()">
                <xsl:text>,</xsl:text>
            </xsl:if>
        </xsl:for-each>
    </cat-id>
</xsl:template>

</xsl:stylesheet>

如果您有许多值,则可以通过使用键来提高效率。但是在XSLT 1.0中将键指向另一个文档(在本例中为XSLT样式表本身)是很尴尬的。