【问题标题】:How to use XSLT in a search-replace scenario?如何在搜索替换场景中使用 XSLT?
【发布时间】:2010-12-18 13:24:21
【问题描述】:

我有一个 XML 文件,在某些位置具有某些值。我希望能够在这些位置替换/添加/删除值。

给出如下:

  1. 所有位置仅引用属性节点。
  2. 如果位置引用不存在的属性节点,则所有者元素节点必须存在。
  3. 新值在编写 XSL 文件时是已知的。

鉴于这些条件,我实现了一个临时解决方案,它接受 XAML 文件中的键值列表,其中键是 XPATH,值是值,并且正是我需要的,只是意识到,我已经有法拉利的时候发明了轮子——XSL变换。

我的问题是这样的。给定一个 XML,XSL 是什么,在该 XML 上应用哪个:

  1. /a/b/@c 处的值替换为另一个值,例如D。如果某些 /a/b 元素没有 c 属性 - 应该添加它。
  2. 删除属性/a/d/@e(如果存在)。否则什么都不做。

谢谢。

【问题讨论】:

    标签: xml xslt


    【解决方案1】:

    XSLT 1.0:

    <!-- the identity template copies everything not matched elsewhere -->
    <xsl:template match="node()|@*">
      <xsl:copy>
        <xsl:apply-templates select="node()|@*" />
      </xsl:copy>
    </xsl:template>
    
    <!-- special handling for /a/b elements -->
    <xsl:template match="/a/b">
      <!-- copy the element itself -->
      <xsl:copy>
        <!-- handle all attributes -->
        <xsl:apply-templates select="@*" />
        <!-- create (or overwrite!) an attribute named "c" -->
        <xsl:attribute name="c">
          <xsl:value-of select="'D'" />
        </xsl:attribute>
        <!-- handle all other child nodes -->
        <xsl:apply-templates select="node()" />
      </xsl:copy>
    </xsl:template>
    
    <!-- empty template to delete /a/d/@e -->
    <xsl:template match="/a/d/@e" />
    

    【讨论】:

    • 我现在正在检查它,但它有点复杂,因为没有保留空格。是否可以保留所有空格?
    • @mark:实际上,使用这种方法(通过身份模板)可以保留空格。您能否为您指定它们丢失的位置?
    • 无处不在。我正在使用 altovaxml 免费命令行实用程序来应用 XSL,如下所示:altovaxml /xslt1 Transform.xslt /in App.config /out 1.xml。生成的 XML 文件在元素之间没有空格 - 都是一长行。
    • @mark:这可能是 XSLT 处理器的配置问题。请问可以和 MSXSL 交叉检查吗? microsoft.com/downloads/en/…
    • 是的,msxsl 确实输出了空格。谢谢。
    【解决方案2】:

    我建议您在这里对 XSL 的概念化可能会有些错误。听起来好像您是在程序上想象它,即“我如何表达 'Do X to Y'”而不是“从结构 X 到结构 Y 的映射是什么”,这才是 XSL 的真正含义。

    你会想要这样的东西:

    <xsl:for-each select="//a">
        <xsl:copy>
            <xsl:for-each select="b">
                <xsl:copy>
                    <xsl:attribute name="c">
                        <xsl:value-of select="$D"/> 
                    </xsl:attribute> 
                </xsl:copy>
            </xsl:for-each
        </xsl:copy>
    </xsl:for-each>
    

    (注意,“$D”语法表示变量取消引用,即“插入变量 D 的值”。我猜这就是你想要的,但你可以从任何地方获取 D。)

    因此,您实际上不需要告诉 XSL 'add c' 或 'delete e'。你告诉它应该有什么,否则它什么也不做。

    【讨论】:

    • xsl:copy 上没有定义select 属性,请参阅w3.org/TR/xslt#copying
    • 爆炸。混淆copycopy-of。固定的。但是,我认为它不值得一票否决。
    • Tom,即使使用正确的语法,我也不认为您使用嵌套 for-each 的方法对于已发布的问题来说是一个好的方法。它不考虑可能存在的其他元素,它不处理复制d 元素但删除它们的e 属性,它不灵活且易于扩展。 Tomalak 使用身份转换模板发布的方法,然后添加模板覆盖那些需要更改的节点的行为,在我看来是正确的 XSLT 方法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多