我在尝试抓取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() != '']
会有所帮助,但事实并非如此。
答案 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" />
现在您拥有第一个(按文档顺序!)非空值,您可以根据需要继续重新格式化。