XSLT中的模式匹配元素名称

时间:2015-11-09 10:35:03

标签: xml xslt

我需要遍历XML树并确保某些元素附加了一个属性,如果缺少则添加它。需要这些属性的元素都具有公共元素名称前缀,并且具有此前缀的所有元素都需要属性。

这是一个人为的例子,因为我无法分享实际的XML:

<people>
  <person>
    <PRJ_NAME>Bob</PRJ_NAME>
    <PRJ_AGE>22</PRJ_AGE>
    <address>
      <PRJ_FIRST_LINE>1 Test Street</PRJ_FIRST_LINE>
      <PRJ_SECOND_LINE>London</PRJ_SECOND_LINE>
    </address>
  </person>
  <person>
    <PRJ_NAME>Tony</PRJ_NAME>
    <PRJ_AGE>43</PRJ_AGE>
    <address>
      <PRJ_FIRST_LINE>23 Test Lane</PRJ_FIRST_LINE>
      <PRJ_SECOND_LINE>Edinburgh</PRJ_SECOND_LINE>
    </address>
  </person>
</people>

所需的输出是将m(已修改)属性添加到前缀为PRJ_的所有元素。这些元素嵌套到不同的级别,并且树是非平凡的,所以我不能只对路径进行硬编码:

<people>
  <person>
    <PRJ_NAME m="2015-11-09">Bob</PRJ_NAME>
    <PRJ_AGE m="2015-11-09">22</PRJ_AGE>
    <address>
      <PRJ_FIRST_LINE m="2015-11-09">1 Test Street</PRJ_FIRST_LINE>
      <PRJ_SECOND_LINE m="2015-11-09">London</PRJ_SECOND_LINE>
    </address>
  </person>
  <person>
    <PRJ_NAME m="2015-11-09">Tony</PRJ_NAME>
    <PRJ_AGE m="2015-11-09">43</PRJ_AGE>
    <address>
      <PRJ_FIRST_LINE m="2015-11-09">23 Test Lane</PRJ_FIRST_LINE>
      <PRJ_SECOND_LINE m="2015-11-09">Edinburgh</PRJ_SECOND_LINE>
    </address>
  </person>
</people>

到目前为止,我一直在根据其他SO答案开展工作,例如adding attribute to the node,它适用于单个元素名称,但我很难将其应用于元素名称的模式:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="xs"
    version="2.0">

    <xsl:variable name="dateNow" select="format-date(current-date(), '[Y0001]-[M01]-[D01]')"/>

    <xsl:template match="node()|@*">
      <xsl:copy>
          <xsl:apply-templates select="node()|@*"/>
      </xsl:copy>
    </xsl:template>
    <xsl:template match="PRJ_FIRST_NAME">
        <PRJ_FIRST_NAME m="{$dateNow}">
            <xsl:apply-templates select="@*|node()"/>
        </PRJ_FIRST_NAME>
    </xsl:template>
</xsl:stylesheet>

1 个答案:

答案 0 :(得分:1)

将该模板更改为

<xsl:template match="*[starts-with(local-name(), 'PRJ_') and not(@m)]">
    <xsl:element name="{name()}">
        <xsl:attribute name="m" select="$dateNow"/>
        <xsl:apply-templates select="@*|node()"/>
    </xsl:element>
</xsl:template>

并且您的方法很好,但我想要获得您在结果示例中显示的格式,您需要使用<xsl:variable name="dateNow" select="format-date(current-date(), '[Y0001]-[M01]-[D01]')"/>

http://xsltransform.net/94rmq63在线。