2015-11-09 58 views
1

我需要遍历一个XML树,并确保某些元素具有附加到它们的属性,如果缺失则添加它。需要这些属性的元素都具有公共元素名称前缀,并且具有此前缀的所有元素都需要该属性。XSLT中的模式匹配元素名称

这里的一个人为的例子,因为我不能够共享实际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

更改该模板

<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> 

一nd你的方法很好,虽然我认为要得到你在结果样本中显示的格式,你需要使用<xsl:variable name="dateNow" select="format-date(current-date(), '[Y0001]-[M01]-[D01]')"/>

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

+0

谢谢马丁。本地名称现在看起来非常明显!你对'dateNow'中的错字也是绝对正确的,我已经更新了这个问题,让它专注于名称匹配。干杯! – spikeheap