1

我们有一个程序使用 xml 来保存程序的配置。有人决定重命名我们数据库中的几个值,这些重命名现在也应该在我们客户的配置中向后兼容。

配置示例

<configuration>
    <fruitToEat>yellow_curved_thing</fruitToEat> <!-- should now become banana -->
</configuration>

一个简单的匹配将是(未经测试,只是一个例子):

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

  <xsl:template match"/configuration/fruitToEat/text()">
    <xsl:text>banana</xsl:text>
  </xsl:template>
</xsl:template>

但这只是一个例子,我想这样做 150 次。

是否可以制作一个读取简单文本文件或 ini 文件的 xsl,告诉我 150 个匹配项应该如何相似?

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

  <!-- recreate this template 150 times from an ini file or something -->
  <xsl:template match"/configuration/fruitToEat/text()[.='yellow_curved_thing']">
    <xsl:text>banana</xsl:text>
  </xsl:template>
</xsl:template>

我的映射文件的一个例子可能很简单:

yellow_curved_thing = banana
round_thing = tomato
round_dotted = strawberry

我只想要一个小的 xslt 告诉我:

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

  <!-- recreate this template 150 times from an ini file or something -->
  <xsl:template match"/configuration/fruitToEat/text()[.=$fileRow0]">
    <xsl:text>$fileRow1</xsl:text>
  </xsl:template>
</xsl:template>
4

2 回答 2

0

So even if I think there is more complexity behind the curtain, may be this will help a little bit. There are some possibilities to do this with xlst. Which would be best in long term depends on complexity in real life and how often you need to do this with different "mapping" information.

For your easy example you can put the "mapping" information into a xml file. This could be done by some script form ini file.

<mappings>
    <mapping name="fruitToEat" >
        <map  from="yellow_curved_thing" to="banana"  />
        <map  from="round_thing" to="tomato"  />
        <map  from="round_dotted" to="strawberry"  />
    </mapping>
</mappings>

Than you can have a template which make use of this mapping information:

<xsl:variable name="fruitMapping"
             select="document('fruitmapping.xml')//mapping[@name='fruitToEat']" />

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

    <xsl:template match="/configuration/fruitToEat/text()"  >
        <!-- find the entry in "ini file" -->
        <xsl:variable name ="map" select="$fruitMapping/map[@from = current()]" />
        <xsl:choose>
            <xsl:when test="$map" >
                <xsl:value-of select="$map/@to"/>
            </xsl:when>
            <xsl:otherwise>
                <xsl:copy />
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>

But if this is a onetime job I would implement this "mapping" direct a template. Like this:

<xsl:template match="/configuration/fruitToEat/text()" >
    <xsl:choose>
        <xsl:when test=".='yellow_curved_thing'" >banana</xsl:when>
        <xsl:when test=".='round_thing'" >tomato</xsl:when>
        <xsl:when test=".='round_dotted'" >strawberry</xsl:when>
        <xsl:otherwise>
            <xsl:copy />
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>
于 2013-06-05T12:11:53.360 回答
0

您似乎想根据您的配置文件创建您的 XSLT 动态 XSLT,该配置文件也是一个 XML 文档。考虑到这一点,看看这个例子:

配置.xml

    <p>
  <configuration>
    <fruitToEat>yellow_curved_thing</fruitToEat>
    <mapped>banana</mapped>
  </configuration>
  <configuration>
    <fruitToEat>round_thing</fruitToEat>
    <mapped>tomato</mapped>
  </configuration>
</p>

XSLT:

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

  <xsl:output method="xml" encoding="UTF-8" indent="yes" omit-xml-declaration="yes"/>

  <xsl:template match="/">
    <xsl:element name="xsl:stylesheet">
      <xsl:attribute name="version">
        <xsl:text>1.0</xsl:text>
      </xsl:attribute>
      <xsl:element name="xsl:template">
        <xsl:attribute name="match">
          <xsl:text>node()|@*</xsl:text>
        </xsl:attribute>
        <xsl:element name="xsl:copy">
          <xsl:element name="xsl:apply-templates">
            <xsl:attribute name="select">
              <xsl:text>node()|@*</xsl:text>
            </xsl:attribute>
          </xsl:element>
        </xsl:element>
      </xsl:element>
      <xsl:for-each select="//configuration">
        <xsl:element name="xsl:template">
          <xsl:attribute name="match">
            <xsl:text>configuration/fruitToEat/text()[.=</xsl:text>
            <xsl:text>'</xsl:text>
            <xsl:value-of select="fruitToEat"/>
            <xsl:text>']</xsl:text>
          </xsl:attribute>
          <xsl:element name="xsl:text">
              <xsl:value-of select="mapped"/>
          </xsl:element>
        </xsl:element>
      </xsl:for-each>
    </xsl:element>
  </xsl:template>
</xsl:stylesheet>

输出:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
   <xsl:template match="node()|@*">
      <xsl:copy>
         <xsl:apply-templates select="node()|@*"/>
      </xsl:copy>
   </xsl:template>
   <xsl:template match="configuration/fruitToEat/text()[.='yellow_curved_thing']">
      <xsl:text>banana</xsl:text>
   </xsl:template>
   <xsl:template match="configuration/fruitToEat/text()[.='round_thing']">
      <xsl:text>tomato</xsl:text>
   </xsl:template>
</xsl:stylesheet>
于 2013-06-05T10:38:03.287 回答