I am trying to convert a rally complex fixed length file into XML using DFDL and Daffodil. Each line will be responsible for one element and first element of each line will tell me what kind of element it will be. It can be Parent A or Parent B or it can be child AA or AB or BB or BA.
Where Parent A is one element ,Parent B is another and Child AA is first child of Element A.
Inside one file there are multiple Parent A and Parent B.
I tried initiator tag even tried choice tag but nothing seems to be working. Can anyone please help me out.
It's difficult to give a complete answer without example data, but using initiators and choices is likely the right approach. There are potentially simpler schemas depending on the specific data, but a generic solution might look something like this:
<xs:schema
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:dfdl="http://www.ogf.org/dfdl/dfdl-1.0/">
<xs:include schemaLocation="org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd" />
<xs:annotation>
<xs:appinfo source="http://www.ogf.org/dfdl/">
<dfdl:format ref="GeneralFormat" lengthKind="delimited" />
</xs:appinfo>
</xs:annotation>
<xs:element name="File">
<xs:complexType>
<xs:sequence>
<xs:element name="Record" maxOccurs="unbounded">
<xs:complexType>
<xs:choice dfdl:initiatedContent="yes">
<xs:element name="ParentA" dfdl:initiator="ParentA:">
<xs:complexType>
<xs:sequence dfdl:separator="%NL;" dfdl:separatorPosition="postfix">
<xs:element name="Content" type="xs:string"/>
<xs:element name="Record" maxOccurs="unbounded">
<xs:complexType>
<xs:choice dfdl:initiatedContent="yes">
<xs:element name="ChildAA" type="xs:string" dfdl:initiator="ChildAA:" />
<xs:element name="ChildAB" type="xs:string" dfdl:initiator="ChildAB:" />
</xs:choice>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="ParentB" dfdl:initiator="ParentB:">
<xs:complexType>
<xs:sequence dfdl:separator="%NL;" dfdl:separatorPosition="postfix">
<xs:element name="Content" type="xs:string" />
<xs:element name="Record" maxOccurs="unbounded">
<xs:complexType>
<xs:choice dfdl:initiatedContent="yes">
<xs:element name="ChildBA" type="xs:string" dfdl:initiator="ChildBA:" />
<xs:element name="ChildBB" type="xs:string" dfdl:initiator="ChildBB:" />
</xs:choice>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:choice>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
This schema has the following features:
Each File has an unbounded number of Record's.
Each Record is a choice of either a ParentA or ParentB element, determined by the dfdl:initiator property.
Each Parent element contains the Content for that Parent (i.e. the stuff following the parent initiator) followed by an unbounded number of Child Records.
Each Child Record is also determined by the dfdl:initator property.
A postfix newline separator is used to determine when Parent Content and Child
content end.
This does not allow a ChildB elements to appear after a ParentA element and vice versa--child elements must always appear after the associated parent element. (If this restriction wasn't important, this schema could be greatly simplified).
The above allows data like this:
ParentA:Parent A Content
ChildAA:Child AA Content
ChildAB:Child AB Content
ParentB:Parent B Content
ChildBB:Child BB Content
ParentA:Parent A Content
ChildAB:Child AB Content
Which would parse into an XML infoset like this:
<File>
<Record>
<ParentA>
<Content>Parent A Content</Content>
<Record>
<ChildAA>Child AA Content</ChildAA>
</Record>
<Record>
<ChildAB>Child AB Content</ChildAB>
</Record>
</ParentA>
</Record>
<Record>
<ParentB>
<Content>Parent B Content</Content>
<Record>
<ChildBB>Child BB Content</ChildBB>
</Record>
</ParentB>
</Record>
<Record>
<ParentA>
<Content>Parent A Content</Content>
<Record>
<ChildAB>Child AB Content</ChildAB>
</Record>
</ParentA>
</Record>
</File>
The above is tested with Apache Daffodil 2.2.0
Related
I am trying to convert a FLAT file to XML using DFDL. It has following format:
Each element is 5 byte.All are in same line but i am separating them to avoid confusion. I will address element by first letter in them.
0AAAA
81AAA
eeeee
qqqqq
82BBB
rrrrr
sssss
9QQQQ
Now 0 and 9 are grandparents we don't have to worry about them. 8 is parent and second byte of 81AAA(that is 1) will determine the format of its children. There can be many 8 and many children of a 8 parent(but all of them will have same format).
I tried one schema but once it go into children(eeeee) its not coming out of it and every record is being printed in children format only.
Below is a schema that I think describes your data, tested on Daffodil 2.2.0:
<xs:schema
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:fn="http://www.w3.org/2005/xpath-functions"
xmlns:dfdl="http://www.ogf.org/dfdl/dfdl-1.0/">
<xs:include schemaLocation="org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd" />
<xs:annotation>
<xs:appinfo source="http://www.ogf.org/dfdl/">
<dfdl:format ref="GeneralFormat" />
</xs:appinfo>
</xs:annotation>
<xs:element name="Root">
<xs:complexType>
<xs:sequence>
<xs:element name="GrandParent" maxOccurs="unbounded">
<xs:complexType>
<xs:choice dfdl:initiatedContent="yes">
<xs:element name="Zero" dfdl:initiator="0">
<xs:complexType>
<xs:sequence>
<xs:element name="Value" type="xs:string" dfdl:length="4" dfdl:lengthKind="explicit" />
<xs:element ref="Eight" minOccurs="0" maxOccurs="unbounded" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="Nine" dfdl:initiator="9">
<xs:complexType>
<xs:sequence>
<xs:element name="Value" type="xs:string" dfdl:length="4" dfdl:lengthKind="explicit" />
<xs:element ref="Eight" minOccurs="0" maxOccurs="unbounded" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:choice>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="Eight" dfdl:initiator="8">
<xs:complexType>
<xs:sequence>
<xs:element name="ChildrenFormat" type="xs:string" dfdl:length="1" dfdl:lengthKind="explicit" />
<xs:element name="Value" type="xs:string" dfdl:length="3" dfdl:lengthKind="explicit" />
<xs:choice dfdl:choiceDispatchKey="{ ./ChildrenFormat }">
<xs:element ref="One" maxOccurs="unbounded" dfdl:choiceBranchKey="1" />
<xs:element ref="Two" maxOccurs="unbounded" dfdl:choiceBranchKey="2" />
</xs:choice>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="One" type="xs:string" dfdl:length="5" dfdl:lengthKind="explicit">
<xs:annotation>
<xs:appinfo source="http://www.ogf.org/dfdl/">
<dfdl:discriminator test="{ fn:not(fn:starts-with(., '8') or fn:starts-with(., '9')) }" />
</xs:appinfo>
</xs:annotation>
</xs:element>
<xs:element name="Two" type="xs:string" dfdl:length="5" dfdl:lengthKind="explicit">
<xs:annotation>
<xs:appinfo source="http://www.ogf.org/dfdl/">
<dfdl:discriminator test="{ fn:not(fn:starts-with(., '8') or fn:starts-with(., '9')) }" />
</xs:appinfo>
</xs:annotation>
</xs:element>
</xs:schema>
A description of how this works:
The Root of the data is an unbounded number of GrandParent elements
Each GrandParent element contains either a Zero or a Nine, based on the initiator. The initiator consumes the first of the 5 bytes of the grandparent data
The Zero/Nine elements contain a Value which consumes the remaining 4 bytes of the gradparent data
Following the Value is zero or more Eight elements
Each Eight element has an initiator of "8", consuming the first of 5 bytes
Each Eight element has a ChildrenFormat, consuming the second of 5 bytes
Each Eight element has a Value, consuming the last 3 of 5 bytes
Each Eight element has an unbounded number of either all One or all Two elements
A choiceDispatchKey/Branch is used to determine whether to parse all One or all Two elements, dispatching off of the ChildrenFormat element
Each One or Two element consumes 5 bytes
In order to determine when the unbounded number of One or Two elements ends, a discriminator is placed on the One/Two elements. This discriminator fails when the data parsed as a One/Two does not start with an '8' or a '9'.
Also, all fields are treated as strings for simplicity
With this, your example data parses to an infoset like so:
<Root>
<GrandParent>
<Zero>
<Value>AAAA</Value>
<Eight>
<ChildrenFormat>1</ChildrenFormat>
<Value>AAA</Value>
<One>eeeee</One>
<One>qqqqq</One>
</Eight>
<Eight>
<ChildrenFormat>2</ChildrenFormat>
<Value>BBB</Value>
<Two>rrrrr</Two>
<Two>sssss</Two>
</Eight>
</Zero>
</GrandParent>
<GrandParent>
<Nine>
<Value>QQQQ</Value>
</Nine>
</GrandParent>
</Root>
I want to change an image in about 110 CR 2008 Reports.
I've seen answer about mass changing fields, but I need to change image.
Is their any script or method I could use ?
if you are saving the image in the database you can create schema xml file to reade from the image from DB and call this schema as subreport in the report itself.
the schema will be like this:
You have to make some modification on the id, target, element(table Name) and source as your requirements.
<?xml version="1.0" encoding="utf-8"?>
<xs:schema id="rptAppSettings" targetNamespace="http://tempuri.org/AppSettings.xsd" xmlns:mstns="http://tempuri.org/AppSettings.xsd" xmlns="http://tempuri.org /AppSettings.xsd" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas- microsoft-com:xml-msdata" xmlns:msprop="urn:schemas-microsoft-com:xml-msprop" attributeFormDefault="qualified" elementFormDefault="qualified">
<xs:annotation>
<xs:appinfo source="urn:schemas-microsoft-com:xml-msdatasource">
<DataSource DefaultConnectionIndex="0" FunctionsComponentName="QueriesTableAdapter" Modifier="AutoLayout, AnsiClass, Class, Public" SchemaSerializationMode="IncludeSchema" xmlns="urn:schemas-microsoft- com:xml-msdatasource">
<Connections>
<Connection AppSettingsObjectName="Web.config" AppSettingsPropertyName="ConnectionString" IsAppSettingsProperty="true" Modifier="Assembly" Name="ConnectionString (Web.config)" ParameterPrefix="#" PropertyReference="AppConfig.System.Configuration.ConfigurationManager.0.ConnectionStrings.ConnectionString.ConnectionString" Provider="System.Data.SqlClient" />
</Connections>
<Tables />
<Sources />
</DataSource>
</xs:appinfo>
</xs:annotation>
<xs:element name="rptAppSettings" msdata:IsDataSet="true" msdata:UseCurrentLocale="true" msprop:Generator_DataSetName="rptAppSettings" msprop:Generator_UserDSName="rptAppSettings">
<xs:complexType>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="App_Settings" msprop:Generator_UserTableName="App_Settings" msprop:Generator_RowEvArgName="App_SettingsRowChangeEvent" msprop:Generator_TableVarName="tableApp_Settings" msprop:Generator_TablePropName="App_Settings" msprop:Generator_RowDeletingName="App_SettingsRowDeleting" msprop:Generator_RowChangingName="App_SettingsRowChanging" msprop:Generator_RowDeletedName="App_SettingsRowDeleted" msprop:Generator_TableClassName="App_SettingsDataTable" msprop:Generator_RowChangedName="App_SettingsRowChanged" msprop:Generator_RowEvHandlerName="App_SettingsRowChangeEventHandler" msprop:Generator_RowClassName="App_SettingsRow">
<xs:complexType>
<xs:sequence>
<xs:element name="LogoImage" msprop:Generator_ColumnVarNameInTable="columnLogoImage" msprop:Generator_ColumnPropNameInRow="LogoImage" msprop:Generator_ColumnPropNameInTable="LogoImageColumn" msprop:Generator_UserColumnName="LogoImage" type="xs:base64Binary" minOccurs="0" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:choice>
</xs:complexType>
</xs:element>
</xs:schema>
I have a source schema with less elements than the destination schema. When I run the map only mapped elements in destination schema shows up. I want all the elements in destination schema to show up, even they are empty. How to do this?
Set the "Default Value" of the output schema. This will create empty nodes.
The most convenient way is to use Inline C# Scripting functoid for this.
Scripting functoid:
public string GetEmptyString()
{
return System.String.Empty;
}
You can just link this functoid to all output nodes where you wish to see empty node.
Example:
Input schema:
<xs:schema xmlns="http://person" targetNamespace="http://person" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="Person">
<xs:complexType>
<xs:sequence>
<xs:element name="Name" type="xs:string" />
<xs:element name="Surname" type="xs:string" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Output schema:
<xs:schema xmlns="http://employee"
targetNamespace="http://employee"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="Employee">
<xs:complexType>
<xs:sequence>
<xs:element name="FirstName" type="xs:string" />
<xs:element name="MidName" type="xs:string" />
<xs:element name="LastName" type="xs:string" />
<xs:element name="Age" type="xs:string" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Input message:
<ns0:Person xmlns:ns0="http://person">
<Name>John</Name>
<Surname>Snow</Surname>
</ns0:Person>
Expected output message:
<ns0:Employee xmlns:ns0="http://employee">
<FirstName>John</FirstName>
<MidName />
<LastName>Snow</LastName>
<Age />
</ns0:Employee>
Solution:
Link Person.Name to Employee.FirstName
Link Person.Surname to Employee.LastName
Create Scripting functoid that returns empty string
Link Scripting functoid to Employee.MidName
Link Scripting functoid to Employee.Age
I have a very strange behaviour in the Show Promotions Dialog in BizTalk 2006. It allows me to promote property fields:
But distinguished fields are disabled:
Any thoughts?
This is the XML Schema generated by the SQL Transport Schema Generation Wizard:
<?xml version="1.0" encoding="utf-16" ?>
<xs:schema xmlns:b="http://schemas.microsoft.com/BizTalk/2003" xmlns="http://ExecutionPlanner.InitializeStep" attributeFormDefault="unqualified" elementFormDefault="qualified" targetNamespace="http://ExecutionPlanner.InitializeStep" version="1.0" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:annotation>
<xs:appinfo>
<msbtssql:sqlScript value="exec [InitizializeStep] #ORCHESTRATION_NAME=" ", #PROVIDER_NAME=" ", #STEP_NAME=" "" xmlns:msbtssql="http://schemas.microsoft.com/BizTalk/2003" />
</xs:appinfo>
</xs:annotation>
<xs:element name="Step">
<xs:complexType>
<xs:sequence minOccurs="1" maxOccurs="1">
<xs:element name="OrchestrationID" type="OrchestrationIDType" />
<xs:element name="Message" type="MessageType" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:complexType name="OrchestrationIDType">
<xs:simpleContent>
<xs:extension base="xs:string" />
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="MessageType">
<xs:simpleContent>
<xs:extension base="xs:string" />
</xs:simpleContent>
</xs:complexType>
</xs:schema>
Edit your schema to change the OrchestrationID field from a Record to a Field Element. Only Elements and Attributes can be distinguished.
This usually entails deleting the existing Record element, then re-creating an Element with the same name, as Visual Studio wont allow changing an xml node's type. However, you can get around this by opening the xsd file using the XML (Text) Editor using the 'Open With...' option.
Very new to .Net. Everything was working fine until I added <Tracking> to my XML file:
<Product>
<id>product1</id>
<Name>Product 1</Name>
<Packart>detailimg</Packart>
<TitleFile>detailtitleoriginal</TitleFile>
<Description>Description</Description>
<Ingredients>Ingredients</Ingredients>
<FeedingInstructions>Instructions</FeedingInstructions>
<Analysis>Analysis</Analysis>
<Footer>Footer</Footer>
**<Tracking>Test</Tracking>**
</Product>
My XSD file is such:
<?xml version="1.0" encoding="utf-8" ?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="Products">
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="unbounded" name="Product">
<xs:complexType>
<xs:sequence>
<xs:element name="id" type="xs:string" />
<xs:element name="Name" type="xs:string" />
<xs:element name="Packart" type="xs:string" />
<xs:element name="TitleFile" type="xs:string" />
<xs:element name="Description" type="xs:string" />
<xs:element name="Ingredients" type="xs:string" />
<xs:element name="FeedingInstructions" type="xs:string" />
<xs:element name="Analysis" type="xs:string" />
<xs:element name="Footer" type="xs:string" />
<xs:element name="Tracking" type="xs:string" /></xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Then in my aspx page I added:
<%=row[ "Tracking"]%>
When I view the page in a browser I get the error:
Failed to enable constraints. One or more rows contain values violating non-null, unique, or foreign-key constraints.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.Data.ConstraintException: Failed to enable constraints. One or more rows contain values violating non-null, unique, or foreign-key constraints.
Source Error:
Line 19: ds = new System.Data.DataSet();
Line 20: ds.ReadXmlSchema(MapPath("Content/xml/Products.xsd"));
Line 21: ds.ReadXml(MapPath("Content/xml/Products.xml"));
Line 22: Cache.Insert("Products", ds, new System.Web.Caching.CacheDependency(MapPath("Content/xml/Products.xml")),
Line 23: DateTime.Now.AddHours(12), System.Web.Caching.Cache.NoSlidingExpiration);
Source File: d:\ProductDetails.aspx.cs Line: 21
One way to overcome this issue quickly is to disable EnforceConstraints on the dataset:
ds.EnforceConstraints = false;
//now you can load the data
UPDATE: This may have unwanted repercussions, obviously. You should decide whether this is the case or not in your scenario.