It is legal to have more than one assertion. Pattern assertions are
always evaluated before the data is parsed and expression assertions are
evaluated after data is parsed.

Regarding the warning, the issue here is the second assert you have:

  { fn:count(field) eq fn:count(../record[1]/field) }

This expression tries to access the first record element with
../record[1]. So it goes up to the parent element (csv) and then steps
down to the record array and gets the first element. But there are
actually two record arrays that are children of the csv element, one in
each branch of the choice. So depending on how things are parsed, this
expression could access either of those arrays, which could cause
Daffodil to cause an SDE in some cases. (Daffodil is strict about
knowing exactly which element will be access, in this case it's
ambiguous so there is a warning).

Now, technically Daffodil probably could know that because one record
array is in a different choice branch than the expression that it could
never actually reference that one, but our expression compilation
doesn't currently know that. But as schema authors, we do know that the
second expression will never get confused and reference the wrong thing,
and so the warning could be ignored.

That said, there are two ways to get rid of this warning.

1) Just give your record arrays different names. That's kindof
unfortunately because you really do want them to have the same name.

2) Do not use a choice for determining header optionality, but make the
header an optional element. Then you truly only have a single record
array. So remove the choice, you header element becomes something like this:

  <xs:element name="header" type="headerType" minOccurs="0"
    dfdl:occursCountKind="expression"
    dfdl:occursCount="{ if ($header eq 'present') then 1 else 0 }" />

And then your record assert becomes something like this:

  <dfdl:assert test="{
    if ($header eq 'present')
    then fn:count(field) eq fn:count(../header[1]/title)
    else fn:count(field) eq fn:count(../record[1]/field) }" />

Note that because header is now optional, Daffodil treats it like an
array so you need to access it with the [1] index.

- Steve


On 11/11/19 7:30 AM, Costello, Roger L. wrote:
> Hi Folks,
> 
> Per Brandon’s (excellent) suggestion, I added an assertion on each record 
> element to test that it contains the same number of field elements as the 
> first 
> record. See below. Notice that I have a choice to deal with the case where 
> the 
> CSV file does and doesn’t have a header. Notice in the second branch of the 
> choice I have two assertions – is it legal to have multiple assertions? When 
> I 
> run my schema I get this error message:
> 
> *[warning] Schema Definition Warning: Statically ambiguous or query-style 
> paths 
> not supported in step path: '{}record'.*
> 
> What does that mean? How to fix it?  /Roger
> 
> <xs:elementname="csv">
> <xs:complexType>
> <xs:sequence>
> <xs:choicedfdl:choiceDispatchKey="{$header}">
> <xs:sequencedfdl:choiceBranchKey="present">
> <xs:sequencedfdl:separator="%NL;"dfdl:separatorPosition="infix">
> <xs:elementname="header"type="headerType"/>
> <xs:elementname="record"type="recordType"maxOccurs="unbounded">
> <xs:annotation>
> <xs:appinfosource="http://www.ogf.org/dfdl/";>
> <dfdl:asserttest="{ fn:count(field) eq fn:count(../header/title) }"
>                                          message="{'Each record should 
> contain 
> the same number of fields as the header.'}"/>
> </xs:appinfo>
> </xs:annotation>
> </xs:element>
> </xs:sequence>
> </xs:sequence>
> <xs:sequencedfdl:choiceBranchKey="absent">
> <xs:sequencedfdl:separator="%NL;"dfdl:separatorPosition="infix">
> <xs:elementname="record"type="recordType"maxOccurs="unbounded">
> <xs:annotation>
> <xs:appinfosource="http://www.ogf.org/dfdl/";>
> <dfdl:asserttest="{ fn:count(field) eq fn:count(../record[1]/field) }"
>                                          message="{'Each record should 
> contain 
> the same number of fields.'}"/>
> <dfdl:asserttestKind="pattern"testPattern="."
>                                          message="{'If the last record is 
> empty, 
> then no fields should be generated'}"/>
> </xs:appinfo>
> </xs:annotation>
> </xs:element>
> </xs:sequence>
> </xs:sequence>
> </xs:choice>
> <xs:sequencedfdl:hiddenGroupRef="hidden-newline"/>
> </xs:sequence>
> </xs:complexType>
> </xs:element>
> 

Reply via email to