将多个属性值更改为新值

时间:2012-12-20 19:43:27

标签: xml xslt

这个问题是从使用XSLT: Change certain attribute values的答案来解决我的情况,但发现它不起作用。

这是我的xml:

<root>
<Element1 id="VEH1">
    <Element2 />
</Element1>
<Element1 id="VEH2">
    <Element2 />
</Element1>
</root>

这是我的xsl转换:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="@*|node()">
  <xsl:copy>
    <xsl:apply-templates select="@*|node()"/>
  </xsl:copy>
</xsl:template>
<xsl:template match="@id">
  <xsl:attribute name="id">
    <xsl:choose>
      <xsl:when test=". = VEH1">
        <xsl:text>VEH01</xsl:text>
      </xsl:when>
      <xsl:when test=". = VEH2">
        <xsl:text>VEH02</xsl:text>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="." />
      </xsl:otherwise>
    </xsl:choose>
  </xsl:attribute>
</xsl:template>
</xsl:stylesheet>

我希望输出看起来像:

<?xml version="1.0" encoding="UTF-8"?><root>
<Element1 id="VEH01">
    <Element2/>
</Element1>
<Element1 id="VEH02">
    <Element2/>
</Element1>
</root>

但属性值保持不变,至少在http://xslttest.appspot.com/,我不知道为什么。感谢

3 个答案:

答案 0 :(得分:2)

  <xsl:when test=". = VEH1">
    <xsl:text>VEH01</xsl:text>
  </xsl:when>
  <xsl:when test=". = VEH2">
    <xsl:text>VEH02</xsl:text>
  </xsl:when>

您缺少文字'VEH1''VEH2'

周围的单引号

答案 1 :(得分:2)

这个简单,简短且完整的转换不使用任何显式XSLT条件指令:

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

    <xsl:template match="Element1[starts-with(@id,'VEH')]">
     <Element1 id="VEH0{substring-after(@id,'VEH')}">
      <xsl:apply-templates select="@*[not(name()='id')]|node()"/>
     </Element1>
    </xsl:template>
</xsl:stylesheet>

在提供的XML文档上应用此转换时:

<root>
    <Element1 id="VEH1">
        <Element2 />
    </Element1>
    <Element1 id="VEH2">
        <Element2 />
    </Element1>
</root>

产生了想要的正确结果:

<root>
   <Element1 id="VEH01">
      <Element2/>
   </Element1>
   <Element1 id="VEH02">
      <Element2/>
   </Element1>
</root>

<强>解释

  1. identity rule 按“原样”复制已选择执行该节点的每个节点。

  2. 有一个覆盖模板匹配任何名为Element1且具有id属性的元素,其字符串值以字符串“VEH”开头。

  3. 该元素将重新创建为具有相同名称的文字结​​果元素,并且id属性具有新的所需字符串值。 AVT (属性值模板)用于缩短代码并使其更具可读性。

  4. 在这样创建的元素的主体中,模板应用于所有非id属性和所有子节点 - 这些属性由身份模板匹配并“按原样”复制。 / p>

  5. <强>更新

    @wst建议,只有当这个数字是一个数字时,结尾的数字才应该用零填充。

    这是稍微修改过的解决方案,适用于这种情况:

    <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:template match="node()|@*">
            <xsl:copy>
                <xsl:apply-templates select="node()|@*"/>
            </xsl:copy>
        </xsl:template>
    
        <xsl:template match=
        "Element1[starts-with(@id,'VEH')
                and string-length(@id)=4
                and floor(substring(@id,4)) = floor(substring(@id,4))
                 ]">
         <Element1 id="VEH0{substring-after(@id,'VEH')}">
          <xsl:apply-templates select="@*[not(name()='id')]|node()"/>
         </Element1>
        </xsl:template>
    </xsl:stylesheet>
    

    在此XML文档上应用此转换时:

    <root>
        <Element1 id="VEH1">
            <Element2 />
        </Element1>
        <Element1 id="VEH2">
            <Element2 />
        </Element1>
        <Element1 id="VEH12">
            <Element3 />
        </Element1>
    </root>
    

    产生了想要的,正确的(关于新添加的要求)结果:

    <root>
       <Element1 id="VEH01">
          <Element2/>
       </Element1>
       <Element1 id="VEH02">
          <Element2/>
       </Element1>
       <Element1 id="VEH12">
          <Element3/>
       </Element1>
    </root>
    

答案 2 :(得分:2)

有一种相当简单的方法 - 只需使用此模板:

<xsl:template match="@id[starts-with(.,'VEH')]">
  <xsl:attribute name="id">
    <xsl:value-of select="concat('VEH',format-number(substring(.,4),'00'))" />
  </xsl:attribute>
</xsl:template>

如果需要,您可以进一步限制匹配的谓词 - 如果and (floor(substring(.,4)) = substring(.,4))之后有任何其他数字,则可以添加VEH