1

我有一个具有特定属性 (myId) 的文档,只要它的值为零,就需要更新它的值。文件看起来像这样

<?xml version="1.0" encoding="UTF-8"?><Summary>
 <Section myId="0">
  <Section myId="0">
   <Para>...</Para>
  </Section>
  <Section myId="5">
   <Para>...</Para>
  </Section>
 </Section>
</Summary>

我正在使用模板来匹配属性 myId 以便将其设置为从调用程序传递的唯一 ID,但我只想匹配文档中的一个属性。任何值为 0 的附加属性都将通过传递不同的 ID 进行更新。我正在使用的模板如下所示:

 <xsl:template        match  = '@myId[.="0"]'>
  <xsl:attribute name = "{name()}">
   <xsl:value-of select = "$addValue"/>
  </xsl:attribute>
 </xsl:template>

值 addValue 是从调用程序传递的全局参数。我在一天的大部分时间里都在寻找答案,但我无法让这个模板只应用一次。输出将两个 myId 值替换为 addValue 的内容。我尝试与 '@myId[."0"][1]' 匹配,并尝试使用 position() 函数进行匹配,但我的模板始终应用于所有为零的 myId 属性。

是否可以只应用一次匹配的模板?

4

1 回答 1

1

是否可以只应用一次匹配的模板?

是的

  1. 是否应用模板取决于xsl:apply-templates导致选择模板执行的原因。

  2. 另外,匹配模式可以通过一种方式指定,以保证模板只匹配文档中的一个特定节点。

这是您可以执行的操作

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

 <xsl:param name="pNewIdValue" select="9999"/>


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

 <xsl:template match=
 "Section
   [@myId = 0
  and
    not((preceding::Section | ancestor::Section)
                 [@myId = 0]
       )
   ]/@myId">
  <xsl:attribute name="myId"><xsl:value-of select="$pNewIdValue"/></xsl:attribute>
 </xsl:template>
</xsl:stylesheet>

当此转换应用于提供的 XML 文档时

<Summary>
    <Section myId="0">
        <Section myId="0">
            <Para>...</Para>
        </Section>
        <Section myId="5">
            <Para>...</Para>
        </Section>
    </Section>
</Summary>

产生了想要的正确结果:

<Summary>
   <Section myId="9999">
      <Section myId="0">
         <Para>...</Para>
      </Section>
      <Section myId="5">
         <Para>...</Para>
      </Section>
   </Section>
</Summary>
于 2012-05-05T02:40:56.310 回答