根据另一个标签的值,向XML标记添加属性。

4

我很难理解xslt...试图转换以下xml:

<employees>
    <employee>
        <employeeNumber>1234</employeeNumber>
        <startdate>01/02/2003</startdate>
        <activeFlag>true</activeFlag>
        <firstname>Erik</firstname>
        <address>
            <addressline1>123 Main</addressline1>
            <zip>07016</zip>
            <state>New Jersey</state>
            <city>My City</city>
        </address>
    </employee>
</employees>

将此内容转换为以下格式(即将activeFlag标签值提取出来,放入employee标签的属性中):

将activeFlag标签值提取出来,放入employee标签的属性中。

<employees>
    <employee active="true">
            <employeeNumber>1234</employeeNumber>
            <startdate>01/02/2003</startdate>
            <firstname>Erik</firstname>
            <address>
                <addressline1>123 Main</addressline1>
                <zip>07016</zip>
                <state>New Jersey</state>
                <city>My City</city>
            </address>
    </employee>
</employees>

我尝试了以下的XSLT,但它什么也没做:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="employees/employee">       
        <employee active="{activeFlag}"/>
    </xsl:template>

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

有什么想法吗?
2个回答

3
这份XSLT 1.0样式表:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output indent="yes"/>
  <xsl:strip-space elements="*"/>

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

  <xsl:template match="employee">
    <xsl:copy>
      <xsl:if test="activeFlag">
        <xsl:attribute name="active"><xsl:value-of select="activeFlag"/></xsl:attribute>
      </xsl:if>
      <xsl:apply-templates/>      
    </xsl:copy>
  </xsl:template>

  <xsl:template match="activeFlag"/>

</xsl:stylesheet>

应用于您的示例XML会产生以下结果:
<employees>
   <employee active="true">
      <employeeNumber>1234</employeeNumber>
      <startdate>01/02/2003</startdate>
      <firstname>Erik</firstname>
      <address>
         <addressline1>123 Main</addressline1>
         <zip>07016</zip>
         <state>New Jersey</state>
         <city>My City</city>
      </address>
   </employee>
</employees>

如果你确定activeFlag一定存在或者无论它是否存在,你都不在意创建该属性,那么你可以删除xsl:if

此外,你的样式表之所以不起作用是因为你没有在employees/employee匹配中应用模板。你也可以使用以下模板:

  <xsl:template match="employees/employee">       
    <employee active="{activeFlag}">
      <xsl:apply-templates/>
    </employee>
  </xsl:template>

3

这个简短而简单(没有显式条件指令)的转换:

<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="employee">
   <employee active="{activeFlag}">
     <xsl:apply-templates select="node()|@*"/>
   </employee>
 </xsl:template>

 <xsl:template match="activeFlag"/>
</xsl:stylesheet>

应用于提供的XML文档时:

<employees>
    <employee>
        <employeeNumber>1234</employeeNumber>
        <startdate>01/02/2003</startdate>
        <activeFlag>true</activeFlag>
        <firstname>Erik</firstname>
        <address>
            <addressline1>123 Main</addressline1>
            <zip>07016</zip>
            <state>New Jersey</state>
            <city>My City</city>
        </address>
    </employee>
</employees>

产生所需的、正确的结果:

<employees>
  <employee active="true">
    <employeeNumber>1234</employeeNumber>
    <startdate>01/02/2003</startdate>
    <firstname>Erik</firstname>
    <address>
      <addressline1>123 Main</addressline1>
      <zip>07016</zip>
      <state>New Jersey</state>
      <city>My City</city>
    </address>
  </employee>
</employees>
说明: 覆盖身份规则,使用AVT

如果您想正确处理不存在activeFlag子元素的情况,则变得稍微复杂一些:

 <xsl:template match="employee">
   <employee active=
    "{concat(activeFlag,
             substring('false',
                       1 div not(activeFlag))
             )
      }">
     <xsl:apply-templates select="node()|@*"/>
   </employee>
 </xsl:template>

好的 - 非常感谢你们两个...还有一个后续问题(抱歉没有在OP中包含)。我尝试使用此方法将xmlns、xmlns:xsi和xsi:schemaLocation属性添加到employees标记,但是出现错误。这些是特殊属性吗? - Erik Sorensen
@ErikSorensen:xmlns=不是一个属性,而是一个命名空间声明。如果命名空间URI是静态已知的,则创建命名空间声明没有任何问题。如果在XSLT 1.0中不是这样,那么需要使用涉及xxx:node-set()扩展的技巧来创建动态命名空间。 - Dimitre Novatchev
@ErikSorensen:很高兴我的回答对您有用。为什么不考虑接受它呢? - Dimitre Novatchev

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接