1

这个问题是从使用XSLT的答案演变而来的:更改某些属性值以解决我的情况,但发现它不起作用。

这是我的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/我不知道为什么。谢谢

4

3 回答 3

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'

于 2012-12-20T21:22:18.130 回答
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. 身份规则“按原样”复制已选择执行的每个节点。

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

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

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

更新

@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>
于 2012-12-21T04:20:31.187 回答
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除数字以外的任何内容,请添加。

于 2012-12-22T21:58:50.960 回答