在XML中查找第一个非空值

时间:2014-03-13 12:18:42

标签: xml xslt string

我在尝试抓取xml文件中的第一个非空值时遇到了问题。

以下是XML文件的样子:

<?xml version="1.0"?>
<ROOT>
<Student>
    <Student_id>TEST1</Student_id>
    <last_printed>2014-03-11-08:00</last_printed>
</Student>
<Student>
    <Student_id>TEST3</Student_id>
    <last_printed></last_printed>
</Student>
<Student>
    <Student_id>TEST4</Student_id>
    <last_printed>2014-03-06-08:00</last_printed>
</Student>
</ROOT>

我试图使用此XSLT抓取第一个<last_printed>元素解析日期:

<xsl:variable name="day" select="substring-before(substring-after(substring-after(/ROOT/Student[1]/last_printed[text() != ''], '-'), '-'), '-')"/>
<xsl:variable name="month" select="substring-before(substring-after(/ROOT/Student[1]/last_printed[text() != ''], '-'), '-')"/>
<xsl:variable name="year" select="substring-before(/ROOT/Student[1]/last_printed[text() != ''], '-')"/>

最终结果是显示的日期MMDDYYYY:

<xsl:value-of select="substring(concat($month, $day, $year, $padding), 1, 8)"/>

我尝试将索引[1]放在变量语句中的Student元素上,如上所示,我也尝试将它放在这里:

<xsl:variable name="year" select="substring-before(/ROOT/Student/last_printed[1][text() != ''], '-')"/>

如果我不包含[1],我会收到错误消息:

  

不允许包含多个项目的序列作为substring-after的第一个参数(“2014-03-06-08:00”,“2014-03-11-08:00”)

它抓取XML中的所有日期值。

使用[1],看起来XSLT正在抓住它遇到的第一个元素,但它抓住了一个空元素。

如何抓住第一个非空元素。我认为[text() != '']会有所帮助,但事实并非如此。

2 个答案:

答案 0 :(得分:3)

如何简单地编写模板以匹配所述元素?

<xsl:template match="last_printed[text() and not(preceding::last_printed/text())]">

这将查找具有文本节点的第一个last_printed元素,即不在另一个具有文本节点的last_printed元素之前。


我无法重现你得到的错误,但是这个:

  

不允许包含多个项目的序列作为substring-after的第一个参数(&#34; 2014-03-06-08:00&#34;,&#34; 2014-03-11-08 :00&#34)

显然意味着您提供字符串的序列作为字符串函数的第一个参数(消息大约是substring-after,您的代码只提到substring-before)。

因此,您必须仔细研究您的代码,以找到可能存在多个匹配项的行。

另一件事。使用element[text() != '']时,您假设所有元素都有文本节点,但其中一些是空的,或等于''

但事实并非如此。如果元素没有文本内容,则它们也没有文本节点。因此,像

这样的条件
<xsl:if test="element[text() != '']">

返回&#34; false&#34;对于空元素,因为文本节点不存在,不是因为它们是空字符串。因此,

<xsl:if test="element[text()]">

基本相同。

答案 1 :(得分:2)

我认为你这使得它变得比它需要的复杂得多。尝试从:

开始
<xsl:variable name="firstDate" select="/ROOT/Student[last_printed/text()][1]/last_printed" />

现在您拥有第一个(按文档顺序!)非空值,您可以根据需要继续重新格式化。