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