1

这是我的source.xml:

<entries>
    <entry path="/folder/abc.txt">
        <a>abc</a>
        <b>baz</b>
    </entry>
    <entry path="/other/def.txt">
        <a>foo</a>
        <b>bar</b>
    </entry>    
</entries>

我的 XSLT 看起来像:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
    <xsl:variable name="lookup">
        <pair>
            <key>/folder/abc.txt</key>
            <value>/other/folder/abc.txt</value>
        </pair>
        <pair>
            <key>/other/def.txt</key>
            <value>/other/folder/misc/def.txt</value>
        </pair>
    </xsl:variable>
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

因此我可以重现我的源 xml。我想要的是path使用变量进行更新lookuppath应该匹配key到 return value)。

最终输出将是:

<entries>
    <entry path="/other/folder/abc.txt">
        <a>abc</a>
        <b>baz</b>
    </entry>
    <entry path="/other/folder/misc/def.txt">
        <a>foo</a>
        <b>bar</b>
    </entry>    
</entries>

最新的要求是保持缩进的原样。

我怎样才能做到这一点?

提前致谢。

4

2 回答 2

2

下面的 XSL 模板应该可以做到这一点。它使用 EXSLT 扩展函数将变量转换为节点集。(警告:如果变量中的路径不匹配,则路径将被删除!)

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

  <xsl:variable name="lookup">
    <pair>
      <key>/folder/abc.txt</key>
      <value>/other/folder/abc.txt</value>
    </pair>
    <pair>
      <key>/other/def.txt</key>
      <value>/other/folder/misc/def.txt</value>
    </pair>
  </xsl:variable>

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

  <xsl:template match="entry">
    <xsl:copy>
      <xsl:attribute name="path">
        <xsl:call-template name="replace">
          <xsl:with-param name="input" select="@path"/>
        </xsl:call-template>
      </xsl:attribute>
      <xsl:apply-templates select="*"/>
    </xsl:copy>
  </xsl:template>

  <!-- This template looks through each pair in lookup, finds the one whose
       key matches the input and returns the corresponding value. If none
       match, nothing will be returned. -->    
  <xsl:template name="replace">
    <xsl:param name="input"/>
    <xsl:for-each select="exslt:node-set($lookup)/pair">
        <xsl:if test="key = $input">
          <xsl:value-of select="value"/>
        </xsl:if>
    </xsl:for-each>
  </xsl:template>
</xsl:stylesheet>

你可以看到它在这里工作。

于 2013-08-23T12:18:19.967 回答
1

您可以将查找放在单独的文件中,并通过重新排列使其更容易:

查找.xml:

<entries>
    <entry path="/folder/abc.txt">/other/folder/abc.txt</entry>
    <entry path="/other/def.txt">/other/folder/misc/def.txt</entry>
</entries>

你的 xslt:

<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes" />

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


    <xsl:template match="entry/@path">
        <xsl:variable name="oldpath" select="." />
        <xsl:attribute name="path"><xsl:value-of
            select="document('lookup.xml')/entries/entry[@path = $oldpath]" /></xsl:attribute>
    </xsl:template>

</xsl:stylesheet>

请注意,如果没有匹配项,解决方案将不会保留原始值。

于 2013-08-23T12:57:34.037 回答