在tokenize()中使用XSL XPATH if语句

时间:2018-06-15 12:35:44

标签: xml xslt xpath xslt-3.0

我有一个XML文档,其中包含以下结构的人员列表:

<listPerson>
 <person xml:id="John_de_Foo">
  <persName>
     <forename>John</forename>
     <nameLink>de</nameLink>
     <surname>Foo</surname>
     <role>snake charmer</role>
  </persName>
 </person>
 <person xml:id="John_de_Foo_jr">
  <persName>
     <forename>John</forename>
     <nameLink>de</nameLink>
     <surname>Foo</surname>
     <genname>junior</genname>
  </persName>
 </person>
 <person xml:id="M_de_Foo">
  <persName>
     <forename>M</forename>
     <nameLink>de</nameLink>
     <surname>Foo</surname>
  </persName>
 </person>
 [...]
</listPerson>

我只提取某些字段并将它们与tokenize()连接,以使用XSL 3.0(其中$ doc =当前文档)创建新元素<fullname>

<xsl:template match="listPerson/person"> 
 <fullname>
   <xsl:value-of select="$p/persName/name, $p/persName/forename, $p/persName/nameLink, $p/persName/surname, $p/persName/addName, $p/persName/genName" separator=" "/>
 </fullname>
<xsl:template/>

输出:

<fullname>John de Foo</fullname>
<fullname>John de Foo junior</fullname>
<fullname>M de Foo</fullname>

但是,我想用特定的测试来处理元素<forename>。如果forename/@text是单个首字母,请添加.。新结果将输出:

<fullname>John de Foo</fullname>
<fullname>John de Foo junior</fullname>
<fullname>M. de Foo</fullname>

此外,<forename>元素可能不存在,在这种情况下它应绕过测试。

我可以通过将tokenize()更改为一系列<xsl:if>语句来实现此目的,但如果可能的话,我宁愿尝试在XPATH中解决它。

提前致谢

2 个答案:

答案 0 :(得分:5)

在XPath 2.0中有一个if-then-else expression可以直接在xsl:value-of中使用,如下所示:

<xsl:value-of select="$p/persName/name, if (string-length($p/persName/forename) = 1) then concat($p/persName/forename,'.') else $p/persName/forename , $p/persName/nameLink, $p/persName/surname, $p/persName/addName, $p/persName/genName" separator=" " />

另一种方法是在concat(...)函数中使用if-then-else:

<xsl:value-of select="$p/persName/name, concat($p/persName/forename, if (string-length($p/persName/forename) = 1) then '.' else ''), $p/persName/nameLink, $p/persName/surname, $p/persName/addName, $p/persName/genName" separator=" " />

答案 1 :(得分:3)

如果你希望forename后缀为句号,如果它有一个字符串长度,你可以在XPath 3.1中使用forename!(if (string-length() eq 1) then . || '.' else .)例如在完整的模板中:

  <xsl:template match="persName">
      <fullname>
          <xsl:value-of select="forename!(if (string-length() eq 1) then . || '.' else .), nameLink, surname, genname" separator=" "/>
      </fullname>
  </xsl:template>

https://xsltfiddle.liberty-development.net/bdxtq5

当然,对于不同的表达方式,它会起作用吗$p/persName/forename!(if (string-length() eq 1) then . || '.' else .)