Thanks Steve. That is a wicked cool approach.


Okay, I made the suggested changes. See below. Unfortunately, with this simple 
input CSV file:


Year,Make,Model,Description,Price
1997,Chevy,E350,"ac, abs, moon",2999.99



I get this error message:



[error] Parse Error: Failed to populate record[1]. Cause: Parse Error: 
Assertion failed: Each record should contain the same number of fields.



Why am I getting that error? I checked the input and the number of field 
elements in the first record matches the number of title elements in the 
header.  /Roger


<xs:element name="csv">
    <xs:complexType>
        <xs:sequence>
            <xs:element name="header" type="headerType" minOccurs="0"
                dfdl:occursCountKind="expression"
                dfdl:occursCount="{ if ($header eq 'present') then 1 else 0 }" 
/>
            <xs:element name="record" type="recordType" maxOccurs="unbounded">
                <xs:annotation>
                    <xs:appinfo source="http://www.ogf.org/dfdl/";>
                        <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)
                            }"
                            message="{'Each record should contain the same 
number of fields.'}" />
                    </xs:appinfo>
                </xs:annotation>
            </xs:element>
            <xs:sequence dfdl:hiddenGroupRef="hidden-newline" />
        </xs:sequence>
    </xs:complexType>
</xs:element>





-----Original Message-----
From: Steve Lawrence <[email protected]>
Sent: Monday, November 11, 2019 10:08 AM
To: [email protected]
Subject: [EXT] Re: Statically ambiguous or query-style paths not supported in 
step path ... huh?



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