title: Use of 'following-sibling' in XQuery function to return TIME element if a specific pattern is matched
body: <p>I am attempting to write a function in XQuery that returns me a timestamp from an XML data sequence if a specific pattern of values is detected. The data is actually a test log of a system's api messages</p>
  
  <p>The sample XML data looks similar to the snippet below. If the sequence is found it is assumed that the timestamp (TIME tag) will be the same for each line of the pattern  entry.</p>
  
  <p>The specific pattern I need to detect &amp; return the <code>TIME</code> of - is where there are four <code>&lt;FIELD&gt;TRACK_STATUS&lt;/FIELD&gt;&lt;MODE&gt;VALID&lt;/MODE&gt;</code> entries in sequence followed directly by four <code>&lt;FIELD&gt;MULTI_CHAN_IND&lt;/FIELD&gt;&lt;MODE&gt;MULTI&lt;/MODE&gt;</code> entries in sequence - all with the same timestamp.</p>
  
  <pre><code>&lt;SEQUENCE&gt;&lt;TIME&gt;13.00&lt;/TIME&gt;&lt;TAG&gt;2900&lt;/TAG&gt;&lt;FIELD&gt;TRACK_STATUS&lt;/FIELD&gt;&lt;MODE&gt;INVALID&lt;/MODE&gt;&lt;/SEQUENCE&gt;
  &lt;SEQUENCE&gt;&lt;TIME&gt;13.00&lt;/TIME&gt;&lt;TAG&gt;2900&lt;/TAG&gt;&lt;FIELD&gt;TRACK_STATUS&lt;/FIELD&gt;&lt;MODE&gt;INVALID&lt;/MODE&gt;&lt;/SEQUENCE&gt;
  &lt;SEQUENCE&gt;&lt;TIME&gt;13.00&lt;/TIME&gt;&lt;TAG&gt;2900&lt;/TAG&gt;&lt;FIELD&gt;MULTI_CHAN_IND&lt;/FIELD&gt;&lt;MODE&gt;SINGLE&lt;/MODE&gt;&lt;/SEQUENCE&gt;
  &lt;SEQUENCE&gt;&lt;TIME&gt;13.00&lt;/TIME&gt;&lt;TAG&gt;2900&lt;/TAG&gt;&lt;FIELD&gt;MULTI_CHAN_IND&lt;/FIELD&gt;&lt;MODE&gt;SINGLE&lt;/MODE&gt;&lt;/SEQUENCE&gt;
  &lt;SEQUENCE&gt;&lt;TIME&gt;13.00&lt;/TIME&gt;&lt;TAG&gt;2900&lt;/TAG&gt;&lt;FIELD&gt;MULTI_CHAN_IND&lt;/FIELD&gt;&lt;MODE&gt;SINGLE&lt;/MODE&gt;&lt;/SEQUENCE&gt;
  &lt;SEQUENCE&gt;&lt;TIME&gt;13.00&lt;/TIME&gt;&lt;TAG&gt;2900&lt;/TAG&gt;&lt;FIELD&gt;MULTI_CHAN_IND&lt;/FIELD&gt;&lt;MODE&gt;SINGLE&lt;/MODE&gt;&lt;/SEQUENCE&gt;
  &lt;SEQUENCE&gt;&lt;TIME&gt;14.05&lt;/TIME&gt;&lt;TAG&gt;2900&lt;/TAG&gt;&lt;FIELD&gt;TRACK_STATUS&lt;/FIELD&gt;&lt;MODE&gt;VALID&lt;/MODE&gt;&lt;/SEQUENCE&gt;
  &lt;SEQUENCE&gt;&lt;TIME&gt;14.05&lt;/TIME&gt;&lt;TAG&gt;2900&lt;/TAG&gt;&lt;FIELD&gt;TRACK_STATUS&lt;/FIELD&gt;&lt;MODE&gt;VALID&lt;/MODE&gt;&lt;/SEQUENCE&gt;
  &lt;SEQUENCE&gt;&lt;TIME&gt;14.05&lt;/TIME&gt;&lt;TAG&gt;2900&lt;/TAG&gt;&lt;FIELD&gt;TRACK_STATUS&lt;/FIELD&gt;&lt;MODE&gt;VALID&lt;/MODE&gt;&lt;/SEQUENCE&gt;
  &lt;SEQUENCE&gt;&lt;TIME&gt;14.05&lt;/TIME&gt;&lt;TAG&gt;2900&lt;/TAG&gt;&lt;FIELD&gt;TRACK_STATUS&lt;/FIELD&gt;&lt;MODE&gt;VALID&lt;/MODE&gt;&lt;/SEQUENCE&gt;
  &lt;SEQUENCE&gt;&lt;TIME&gt;14.05&lt;/TIME&gt;&lt;TAG&gt;2900&lt;/TAG&gt;&lt;FIELD&gt;MULTI_CHAN_IND&lt;/FIELD&gt;&lt;MODE&gt;MULTI&lt;/MODE&gt;&lt;/SEQUENCE&gt;
  &lt;SEQUENCE&gt;&lt;TIME&gt;14.05&lt;/TIME&gt;&lt;TAG&gt;2900&lt;/TAG&gt;&lt;FIELD&gt;MULTI_CHAN_IND&lt;/FIELD&gt;&lt;MODE&gt;MULTI&lt;/MODE&gt;&lt;/SEQUENCE&gt;
  &lt;SEQUENCE&gt;&lt;TIME&gt;14.05&lt;/TIME&gt;&lt;TAG&gt;2900&lt;/TAG&gt;&lt;FIELD&gt;MULTI_CHAN_IND&lt;/FIELD&gt;&lt;MODE&gt;MULTI&lt;/MODE&gt;&lt;/SEQUENCE&gt;
  &lt;SEQUENCE&gt;&lt;TIME&gt;14.05&lt;/TIME&gt;&lt;TAG&gt;2900&lt;/TAG&gt;&lt;FIELD&gt;MULTI_CHAN_IND&lt;/FIELD&gt;&lt;MODE&gt;MULTI&lt;/MODE&gt;&lt;/SEQUENCE&gt;
  &lt;SEQUENCE&gt;&lt;TIME&gt;15.94&lt;/TIME&gt;&lt;TAG&gt;2900&lt;/TAG&gt;&lt;FIELD&gt;TRACK_STATUS&lt;/FIELD&gt;&lt;MODE&gt;INVALID&lt;/MODE&gt;&lt;/SEQUENCE&gt;
  &lt;SEQUENCE&gt;&lt;TIME&gt;15.94&lt;/TIME&gt;&lt;TAG&gt;2900&lt;/TAG&gt;&lt;FIELD&gt;TRACK_STATUS&lt;/FIELD&gt;&lt;MODE&gt;INVALID&lt;/MODE&gt;&lt;/SEQUENCE&gt;
  </code></pre>
  
  <p>The function I have attempted to define is as follows but gives run time error with <code>'empty sequence not allowed'</code>. Unfortunately I do not have an IDE where I can set a break point and debug this - I am thinking I can not use following-sibling once I have selected an entry with a <code>FOR</code>.</p>
  
  <pre><code>declare function local:get_multi_track_sequence_time( $msgSeq as element()*) as xs:double {
      for $row in $msgSeq
      where some $entry in $row satisfies($entry/SEQUENCE[TAG='2900' and FIELD='TRACK_STATUS' and MODE='VALID']
                      /following-sibling::SEQUENCE[TAG='2900' and FIELD='TRACK_STATUS' and MODE='VALID']
                      /following-sibling::SEQUENCE[TAG='2900' and FIELD='TRACK_STATUS' and MODE='VALID']
                      /following-sibling::SEQUENCE[TAG='2900' and FIELD='TRACK_STATUS' and MODE='VALID']
                      /following-sibling::SEQUENCE[TAG='2900' and FIELD='MULTI_CHAN_IND' and MODE='MULTI']
                      /following-sibling::SEQUENCE[TAG='2900' and FIELD='MULTI_CHAN_IND' and MODE='MULTI']
                      /following-sibling::SEQUENCE[TAG='2900' and FIELD='MULTI_CHAN_IND' and MODE='MULTI']
                      /following-sibling::SEQUENCE[TAG='2900' and FIELD='MULTI_CHAN_IND' and MODE='MULTI'] )
      return data($row/SEQUENCE/TIME)
  };
  </code></pre>
  
  <p>Thanks. I am a relative newby to XQuery.</p>
  
  <p>---------------------<strong>EDIT - ADDED TEST FUNCTION WITH IDEAS FROM SUGGESTIONS</strong>---------------------</p>
  
  <p>Thanks for the suggestions already received. I have written the following self contained test function based on the helpful information given - the function is unable to match following-sibling's.</p>
  
  <p>The function creates a variable <code>data</code> that contains the test sequence. The function as it stands returns an empty sequence. The requirement is that it returns <code>14.050000</code> to indicate the scalar <code>TIME</code> at which there are four <code>&lt;FIELD&gt;TRACK_STATUS&lt;/FIELD&gt;&lt;MODE&gt;VALID&lt;/MODE&gt;</code> entries in sequence followed directly by four <code>&lt;FIELD&gt;MULTI_CHAN_IND&lt;/FIELD&gt;&lt;MODE&gt;MULTI&lt;/MODE&gt;</code> entries in sequence (i.e. at TIME <code>14.050000</code> in the test data).</p>
  
  <p>(Interestingly it successfully returns a sequence of doubles if only the first expression is used i.e. matches all occurrences of TRACK_STATUS/VALID no following-sibling matches are specified.)</p>
  
  <pre><code>declare function local:get_multi_track_sequence_time( ) as xs:double* {
  
      let $data as element()* := (
  
  &lt;SEQUENCE&gt;&lt;TIME&gt;13.04080&lt;/TIME&gt;&lt;TAG&gt;2900&lt;/TAG&gt;&lt;FIELD&gt;TRACK_STATUS&lt;/FIELD&gt;&lt;MODE&gt;INVALID&lt;/MODE&gt;&lt;/SEQUENCE&gt;,
  &lt;SEQUENCE&gt;&lt;TIME&gt;13.04080&lt;/TIME&gt;&lt;TAG&gt;2900&lt;/TAG&gt;&lt;FIELD&gt;TRACK_STATUS&lt;/FIELD&gt;&lt;MODE&gt;INVALID&lt;/MODE&gt;&lt;/SEQUENCE&gt;,
  &lt;SEQUENCE&gt;&lt;TIME&gt;13.05000&lt;/TIME&gt;&lt;TAG&gt;2900&lt;/TAG&gt;&lt;FIELD&gt;TRACK_STATUS&lt;/FIELD&gt;&lt;MODE&gt;VALID&lt;/MODE&gt;&lt;/SEQUENCE&gt;,
  &lt;SEQUENCE&gt;&lt;TIME&gt;13.06900&lt;/TIME&gt;&lt;TAG&gt;2900&lt;/TAG&gt;&lt;FIELD&gt;MULTI_CHAN_IND&lt;/FIELD&gt;&lt;MODE&gt;SINGLE&lt;/MODE&gt;&lt;/SEQUENCE&gt;,
  &lt;SEQUENCE&gt;&lt;TIME&gt;13.06900&lt;/TIME&gt;&lt;TAG&gt;2900&lt;/TAG&gt;&lt;FIELD&gt;MULTI_CHAN_IND&lt;/FIELD&gt;&lt;MODE&gt;SINGLE&lt;/MODE&gt;&lt;/SEQUENCE&gt;,
  &lt;SEQUENCE&gt;&lt;TIME&gt;14.05000&lt;/TIME&gt;&lt;TAG&gt;2900&lt;/TAG&gt;&lt;FIELD&gt;TRACK_STATUS&lt;/FIELD&gt;&lt;MODE&gt;VALID&lt;/MODE&gt;&lt;/SEQUENCE&gt;,
  &lt;SEQUENCE&gt;&lt;TIME&gt;14.05000&lt;/TIME&gt;&lt;TAG&gt;2900&lt;/TAG&gt;&lt;FIELD&gt;TRACK_STATUS&lt;/FIELD&gt;&lt;MODE&gt;VALID&lt;/MODE&gt;&lt;/SEQUENCE&gt;,
  &lt;SEQUENCE&gt;&lt;TIME&gt;14.05000&lt;/TIME&gt;&lt;TAG&gt;2900&lt;/TAG&gt;&lt;FIELD&gt;TRACK_STATUS&lt;/FIELD&gt;&lt;MODE&gt;VALID&lt;/MODE&gt;&lt;/SEQUENCE&gt;,
  &lt;SEQUENCE&gt;&lt;TIME&gt;14.05000&lt;/TIME&gt;&lt;TAG&gt;2900&lt;/TAG&gt;&lt;FIELD&gt;TRACK_STATUS&lt;/FIELD&gt;&lt;MODE&gt;VALID&lt;/MODE&gt;&lt;/SEQUENCE&gt;,
  &lt;SEQUENCE&gt;&lt;TIME&gt;14.05000&lt;/TIME&gt;&lt;TAG&gt;2900&lt;/TAG&gt;&lt;FIELD&gt;MULTI_CHAN_IND&lt;/FIELD&gt;&lt;MODE&gt;MULTI&lt;/MODE&gt;&lt;/SEQUENCE&gt;,
  &lt;SEQUENCE&gt;&lt;TIME&gt;14.05000&lt;/TIME&gt;&lt;TAG&gt;2900&lt;/TAG&gt;&lt;FIELD&gt;MULTI_CHAN_IND&lt;/FIELD&gt;&lt;MODE&gt;MULTI&lt;/MODE&gt;&lt;/SEQUENCE&gt;,
  &lt;SEQUENCE&gt;&lt;TIME&gt;14.05000&lt;/TIME&gt;&lt;TAG&gt;2900&lt;/TAG&gt;&lt;FIELD&gt;MULTI_CHAN_IND&lt;/FIELD&gt;&lt;MODE&gt;MULTI&lt;/MODE&gt;&lt;/SEQUENCE&gt;,
  &lt;SEQUENCE&gt;&lt;TIME&gt;14.05000&lt;/TIME&gt;&lt;TAG&gt;2900&lt;/TAG&gt;&lt;FIELD&gt;MULTI_CHAN_IND&lt;/FIELD&gt;&lt;MODE&gt;MULTI&lt;/MODE&gt;&lt;/SEQUENCE&gt;,
  &lt;SEQUENCE&gt;&lt;TIME&gt;15.06700&lt;/TIME&gt;&lt;TAG&gt;2900&lt;/TAG&gt;&lt;FIELD&gt;MULTI_CHAN_IND&lt;/FIELD&gt;&lt;MODE&gt;SINGLE&lt;/MODE&gt;&lt;/SEQUENCE&gt;,
  &lt;SEQUENCE&gt;&lt;TIME&gt;15.06700&lt;/TIME&gt;&lt;TAG&gt;2900&lt;/TAG&gt;&lt;FIELD&gt;MULTI_CHAN_IND&lt;/FIELD&gt;&lt;MODE&gt;SINGLE&lt;/MODE&gt;&lt;/SEQUENCE&gt;
  
  )
  
      for $entry in $data
      where $entry/self::SEQUENCE
              [TAG='2900' and FIELD='TRACK_STATUS' and MODE='VALID']
            /following-sibling::*[1]/self::SEQUENCE
              [TAG='2900' and FIELD='TRACK_STATUS' and MODE='VALID']
            /following-sibling::*[1]/self::SEQUENCE
              [TAG='2900' and FIELD='TRACK_STATUS' and MODE='VALID']
            /following-sibling::*[1]/self::SEQUENCE
              [TAG='2900' and FIELD='TRACK_STATUS' and MODE='VALID']
            /following-sibling::*[1]/self::SEQUENCE
              [TAG='2900' and FIELD='MULTI_CHAN_IND' and MODE='MULTI']
            /following-sibling::*[1]/self::SEQUENCE
              [TAG='2900' and FIELD='MULTI_CHAN_IND' and MODE='MULTI']
            /following-sibling::*[1]/self::SEQUENCE
              [TAG='2900' and FIELD='MULTI_CHAN_IND' and MODE='MULTI']
            /following-sibling::*[1]/self::SEQUENCE
              [TAG='2900' and FIELD='MULTI_CHAN_IND' and MODE='MULTI']
  
      return data($entry/TIME)
  };
  </code></pre>