Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Check if a node exists using XSLT

Tags:

xml

xslt

To begin with, I would like to ask, is there a difference between the following two statements for XML nodes:

  1. check whether a node is an empty node;
  2. check whether a node exists or not;

Suppose I have an XML file like this:

<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>

and I want to check whether the "current_onset_date" node exists or not, I used the following XSLT:

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

The for-each loop is some logic that I have to bear with in order for the loop to work. But I actuall got wrong result after running this XSLT, the above xml data won't be grabbed by my XSLT. But I don't think using "current_onset_date =‘‘ ” is correct either, since it is testing for "whether current_onset_date contains nothing".

Could anybody tell me where my mistake is and also help me with my question listed in the beginning, thanks!

like image 863
Kevin Avatar asked Jan 14 '11 18:01

Kevin


2 Answers

It should work except that you've got two "and"'s and you don't need the leading / before current_onset_date.

If you want to check for emptiness as well, you can use:

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

The reason this works is that the string value of an element is the concatenation of all the text inside it, so this expression will only select rows where current_onset_date exists and contains a non-empty string. If you want to exclude elements that contain nothing but whitespace, you can write:

<xsl:for-each select="claim_export_xml_row ">
   <xsl:if test="claim_number =$mother_claim_no and normalize-space( current_onset_date ) != ''">
like image 28
biziclop Avatar answered Sep 19 '22 18:09

biziclop


I would like to ask, is there a difference between the following two statements for XML nodes:

1.check whether a node is an empty node;

2.check whether a node exists or not;

These require different expressions to test for: a node that doesn't exist is not an empty node:

current_onset_date 

this selects any current_onset_date children of the current node. Its boolean value is true() if and only if at least one such child exists, and false() -- otherwise.

current_onset_date/text()

this selects any text node children of any current_onset_date children of the current node. If there are none, its boolean value is false(), otherwise -- true(),

Even if an element doesn't have text-nodes as children, it still may have a non-empty string value, because it may have elements as descendents and some of these element-descendents may have text-node children.

current_onset_date[not(string(.))]

this selects any current_onset_date children of the current node, that have the empty string ('') as their string value. This might qualify well for "empty element".

If by empty you mean an element whose string-value is either empty or white-space-only, then this expression:

current_onset_date[not(normalize-space())]

this selects any current_onset_date children of the current node, that have the empty string ('') or an white-space-only string as their string value.

Could anybody tell me where my mistake is

In your code:

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

the expression in the test attribute is always false() because /current_onset_date means: the top element (of the document) named "current_onset_date" , but the top element in your case is named claim_export_xml

You probably want:

claim_number =$mother_claim_no and current_onset_date 

And if you want the element to be "non-empty", then:

    claim_number =$mother_claim_no 
   and 
    current_onset_date[normalize-space()]  
like image 183
Dimitre Novatchev Avatar answered Sep 21 '22 18:09

Dimitre Novatchev