使用XSLT检查节点是否存在

6
首先,我想问一下,以下两个XML节点语句之间是否存在差异:
  1. 检查节点是否为空节点;
  2. 检查节点是否存在。
假设我有一个像这样的XML文件:
<claim_export_xml>
<claim_export_xml_row>
    <claim_number>37423</claim_number>
    <total_submitted_charges>0</total_submitted_charges>
    <patient_control_no/>

    <current_onset_date>2009-06-07 00:00:00</current_onset_date>

我希望检查“current_onset_date”节点是否存在,我使用了以下XSLT:

<xsl:for-each select="claim_export_xml_row ">
       <xsl:if test="claim_number =$mother_claim_no and /current_onset_date "> 

for-each循环是我必须忍受的一些逻辑,以使循环正常工作。但是在运行此XSLT后,我实际上得到了错误的结果,上面的xml数据不会被我的XSLT抓取。但我也不认为使用“current_onset_date =''”是正确的,因为它测试的是“当前的起始日期是否包含任何内容”。

有人能告诉我我的错误在哪里,并帮助我解决开始列出的问题吗?谢谢!

2个回答

17
我想问一下,下面这两个针对XML节点的语句是否有区别:
1. 检查节点是否为空节点;
2. 检查节点是否存在。 这两者需要使用不同的表达式进行测试:一个不存在的节点不是一个空节点。
current_onset_date 

这个选择器选取当前节点下所有current_onset_date的子节点。当至少有一个这样的子节点存在时,它的布尔值为true(),否则为false()

current_onset_date/text()

这个选择器会选中当前节点的所有current_onset_date子节点中的文本节点。如果没有,它的布尔值为false(),否则为true()

即使一个元素没有文本节点作为子节点,它仍然可能具有非空字符串值,因为它可能有元素作为后代,并且这些元素后代中的一些可能有文本节点子节点。

current_onset_date[not(string(.))]

这个选择器选中当前节点下任何current_onset_date子节点,这些子节点的字符串值为空字符串('')。这可能很适合"空元素"。

如果你所说的空元素是指其字符串值为空或仅包含空格,则此表达式:

current_onset_date[not(normalize-space())]

这个选择器选取当前节点下所有current_onset_date子节点,它们的字符串值为空字符串('')或只包含空格。

请问我的代码哪里有问题?

你的代码:

<xsl:for-each select="claim_export_xml_row ">                            
   <xsl:if test="claim_number =$mother_claim_no 
                              and /current_onset_date ">      

test 属性中的表达式始终为 false(),因为 /current_onset_date 的意思是:文档中名为 "current_onset_date" 的顶级元素,但在您的情况下,顶级元素名为 claim_export_xml

您可能想要的是:

claim_number =$mother_claim_no and current_onset_date 

如果您希望该元素是“非空”的,则可以:

    claim_number =$mother_claim_no 
   and 
    current_onset_date[normalize-space()]  

4

它应该能正常工作,除非你有两个 "and" 并且在 current_onset_date 前面不需要前导斜杠。

如果你想要检查是否为空,你可以使用:

<xsl:for-each select="claim_export_xml_row ">
   <xsl:if test="claim_number =$mother_claim_no and current_onset_date != ''">

这个方法的原理是元素的字符串值等于其中所有文本的连接,因此该表达式只会选择 current_onset_date 存在且包含非空字符串的行。如果您想排除只包含空格的元素,可以写成:

<xsl:for-each select="claim_export_xml_row ">
   <xsl:if test="claim_number =$mother_claim_no and normalize-space( current_onset_date ) != ''">

一旦我去掉前面的 /,它会抱怨这是无效的 xpath,并且 "and" 是一个打字错误,抱歉。 - Kevin
当您删除 / 时,您收到的错误消息是什么?我测试了一个类似的构造,它可以正常工作。 - biziclop
它只是抱怨这个XPath无效,没有具体的理由。然而,我找到了一个解决方法,即使用count(current_onset_date)!=0。您认为这样做的测试正确吗? - Kevin
是的,如果至少有一个具有该名称的标签,则它将返回true,如果没有,则返回false,但我仍然觉得奇怪,如果没有这个解决方法它就无法工作。 - biziclop
@bizilop:我再试了一次,没有加前导斜杠,它成功了!我之前一定输错了什么。谢谢。你也能帮我解决我的初始问题吗? - Kevin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接