【问题标题】:Pattern-matching element names in XSLTXSLT 中的模式匹配元素名称
【发布时间】:2015-11-09 10:35:02
【问题描述】:

我需要遍历一个 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>

【问题讨论】:

    标签: xml xslt


    【解决方案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>
    

    您的方法很好,尽管我认为要获得结果示例中显示的格式,您需要使用&lt;xsl:variable name="dateNow" select="format-date(current-date(), '[Y0001]-[M01]-[D01]')"/&gt;

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

    【讨论】:

    • 谢谢马丁。 local-name 现在看起来很明显!你对dateNow 中的错字也完全正确,我已经更新了问题,让它专注于名称匹配。干杯!
    猜你喜欢
    • 1970-01-01
    • 2015-03-22
    • 1970-01-01
    • 2011-07-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多