测试前一个元素的值是否与每个循环的当前值相同

时间:2015-05-08 21:26:38

标签: xslt xslt-2.0

我有一个xml文件,其中名为identifier的元素可以出现1次以上。存储在这些标识符元素中的值可以是文件名,其他本地标识符,所谓的PID(数字:数字格式)和句柄(http://hdl.handle.net/ .... url)。此信息可以按任何顺序出现,或PID可以是1st或句柄或文件名;它是随机的。我对PID和句柄感兴趣,数据有这三种场景用于PID并在父元素记录中处理:

1)PID仅在标识符元素组中出现一次 2)句柄仅在标识符元素组中出现一次 3)PID和句柄一次出现在标识符元素集中。

在方案1中,我想添加前缀" http://hdl.handle.net/11134/"到PID并将此值放在标识符元素中,然后添加一个元素源,我根据PID构建一个url。

在方案2中,我想将标识符字段的值添加到新xml文件中的相同标识符,并在新的源元素中基于此句柄构建URL。

在方案3中,我想要选择PID或句柄,而不是两者。让我们说我只想要句柄而不是PID,然后我做方案2.

如果同时存在PID和句柄,我有2个标识符和2个源元素,我不知道如何更改它,以便只有场景2才会这样做。

我是xslt的新手,不知道我做错了什么。我尝试了previous-sibling和for-each的变体并选择,但是场景3的结果总是2个标识符元素和2个源元素。

感谢您的帮助。

这是xml的一个示例:

<record>
<identifier>200003:93939393</identifier>
<identifier>sampleFilename.jpg</identifier>
<identifier>otherLocalidentifier</identifier>
<identifier>hdl.handle.net/11134/200003:93939393</identifier>
</record>
<record>
<identifier>otherfilename.tiff</identifier>
<identifier>hdl.handle.net/11134/50003:93939393</identifier>
</record>
<record>
<identifier>somelocal name</identifier>
<identifier>94949:93999393</identifier>
</record>

在这个xml中,标识符还有其他值,标识符元素的数量是随机的,PID和句柄可以按任何顺序出现。

我想要的输出是在新的xml文件中始终只有1个标识符和1个源元素:

<record>
<identifier>hdl.handle.net/11134/200003:93939393</identifier>
<source>200003:93939393/TN</source>
</record>
<record>
<identifier>hdl.handle.net/11134/50003:93939393</identifier>
<source>50003:93939393/TN</source>
</record>
<record>
<identifier>http://hdl.handle.net/11134/94949:93999393</identifier>
<source>94949:93999393/TN</source>
</record>

<xsl:template match="identifier">
<xsl:variable name="idvalue">
<xsl:choose>
<xsl:when test="contains(., 'http://hdl.handle.net/')">
<xsl:value-of select="normalize-space(.)"/>
</xsl:when>
<xsl:when test="matches(., '^\d{5,10}[:]\d*$')">
<xsl:text>http://hdl.handle.net/11134/</xsl:text>
<xsl:value-of select="normalize-space(.)"/>
</xsl:when>
<xsl:otherwise/>
</xsl:choose>
</xsl:variable>
<xsl:value-of select="$idvalue[1]"></xsl:value-of>

2 个答案:

答案 0 :(得分:0)

<强>予。这是正确的XSLT 2.0转换:

std::function

应用于以下XML文档

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>
 <xsl:variable name="vPat"
      select="'(^\d{5,10}:\d+$)|(^hdl.handle.net/11134/\d{5,10}:\d+$)'"/>

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

  <xsl:template match="record/*[matches(., $vPat)][1]">
    <identifier>
     <xsl:value-of select="replace(.,'^(.*?)(\d{5,10}:\d+)$','hdl.handle.net/11134/$2')"/>
    </identifier>
    <source>
      <xsl:value-of select="replace(.,'^(.*?)(\d{5,10}:\d+)$', '$2/TN')"/>
    </source>
  </xsl:template>
  <xsl:template match="record/*" priority="0"/>
</xsl:stylesheet>

生成想要的正确结果

<t>
    <record>
        <identifier>other/Local/12345:67/identifier</identifier>
        <identifier>200003:93939393</identifier>
        <identifier>sampleFilename.jpg</identifier>
        <identifier>hdl.handle.net/11134/200003:93939393</identifier>
    </record>
    <record>
        <identifier>Some/50003:</identifier>
        <identifier>otherfilename.tiff</identifier>
        <identifier>hdl.handle.net/11134/50003:93939393</identifier>
    </record>
    <record>
        <identifier>somelocal name</identifier>
        <identifier>94949:93999393</identifier>
    </record>
</t>

<强> II。这个XSLT 1.0转换:

<t>
   <record>
      <identifier>hdl.handle.net/11134/200003:93939393</identifier>
      <source>200003:93939393/TN</source>
   </record>
   <record>
      <identifier>hdl.handle.net/11134/50003:93939393</identifier>
      <source>50003:93939393/TN</source>
   </record>
   <record>
      <identifier>hdl.handle.net/11134/94949:93999393</identifier>
      <source>94949:93999393/TN</source>
   </record>
</t>

应用于同一XML文档时,再次生成所需的正确结果

<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 priority="3" match=
   "record/*[floor(substring-before(., ':')) = substring-before(., ':')
         and floor(substring-after(., ':')) = substring-after(., ':')
          ]">
    <identifier><xsl:value-of select="concat('hdl.handle.net/11134/',.)"/></identifier>
    <source><xsl:value-of select="concat(., '/TN')"/></source>
  </xsl:template>

  <xsl:template match=
  "record[not(*[floor(substring-before(., ':')) = substring-before(., ':')
             and floor(substring-after(., ':')) = substring-after(., ':')
                ]
             )]
             /*[starts-with(., 'hdl.handle.net/11134/')]">
    <xsl:copy-of select="."/>
    <source><xsl:value-of select="
    concat(substring-after(., 'hdl.handle.net/11134/'), '/TN')"/></source>
  </xsl:template>
  <xsl:template match="text() |identifier"/>
</xsl:stylesheet>

答案 1 :(得分:0)

假设你的正则表达式唯一地标识了一个PID,我建议你这样试试:

XSLT 2.0

<xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

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

<xsl:template match="record">
    <xsl:variable name="pid" select="(identifier/tokenize(., '/')[matches(., '^\d{5,10}[:]\d*$')])[1]"/>
    <xsl:copy>
        <identifier><xsl:value-of select="concat('hdl.handle.net/11134/', $pid)"/></identifier>
        <source><xsl:value-of select="concat($pid, '/TN')"/></source>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

演示:http://xsltransform.net/bFDb2CE/1