Question

I am trying to use ColdFusion's XMLValidate() function to validate an XML Document against the ONIX XSD Schema. ONIX is a 'standard' XML format used by some aspects of the book publishing industry.

This is a sample XML document [I modified some data for Client NDA type reasons; sorry for the length]

<?xml version="1.0"?>
<ONIXMessage release="3.0">
  <Header>       
    <Sender>
      <SenderName>Me</SenderName>   
    </Sender>
    <SentDateTime>20131030T090000Z</SentDateTime>
    <MessageNote>My Test for SO</MessageNote>
  </Header>
  <Product>  
    <RecordReference>12345</RecordReference>     
    <NotificationType>03</NotificationType>
    <RecordSourceType>01</RecordSourceType>
    <RecordSourceName>Me</RecordSourceName>   
    <ProductIdentifier>
      <ProductIDType>15</ProductIDType>
      <IDValue>12324567801011</IDValue>
    </ProductIdentifier>
    <DescriptiveDetail>
      <ProductComposition>00</ProductComposition>
      <ProductForm>ED</ProductForm>
      <ProductFormDetail>E101</ProductFormDetail>
      <ProductFormDetail>E127</ProductFormDetail>
      <PrimaryContentType>10</PrimaryContentType>
      <EpubTechnicalProtection>01</EpubTechnicalProtection>
      <Collection>
        <CollectionType>10</CollectionType>
        <CollectionSequence>
          <CollectionSequenceType>02</CollectionSequenceType>
          <CollectionSequenceNumber>11</CollectionSequenceNumber>
        </CollectionSequence>
        <TitleDetail>
           <TitleType>01</TitleType>
           <TitleElement>
              <TitleElementLevel>02</TitleElementLevel>
              <TitlePrefix><![CDATA[The]]></TitlePrefix>
              <TitleWithoutPrefix><![CDATA[Something]]></TitleWithoutPrefix>
           </TitleElement>
        </TitleDetail>
      </Collection>    
      <TitleDetail>
        <TitleType>01</TitleType>
        <TitleElement>
          <SequenceNumber>1</SequenceNumber>
          <TitleElementLevel>01</TitleElementLevel>
          <TitleText>
            <![CDATA[ForSO]]>
          </TitleText>
        </TitleElement>
        <TitleStatement><![CDATA[The Something for SO]]></TitleStatement>
      </TitleDetail>
      <Contributor>  
        <SequenceNumber>1</SequenceNumber>
        <ContributorRole>A01</ContributorRole>
        <PersonName>Me, Myself</PersonName>
        <PersonNameInverted>Myself, Me</PersonNameInverted>
        <NamesBeforeKey>Myself</NamesBeforeKey>
        <KeyNames>Me</KeyNames>
      </Contributor>
      <Contributor>
        <SequenceNumber>2</SequenceNumber>
        <ContributorRole>A01</ContributorRole>
        <PersonName>Someone Else</PersonName>
        <PersonNameInverted>Else, Someone</PersonNameInverted>
        <NamesBeforeKey>Someone</NamesBeforeKey>
        <KeyNames>Else</KeyNames>
      </Contributor>
      <ContributorStatement>Me Myself and Someone Else</ContributorStatement>
      <Language>
        <LanguageRole>01</LanguageRole>
        <LanguageCode>eng</LanguageCode>
      </Language>
      <Extent>                              
        <ExtentType>00</ExtentType>
        <ExtentValue>40</ExtentValue>
        <ExtentUnit>03</ExtentUnit>
      </Extent>
      <Subject>
        <MainSubject/>
        <SubjectSchemeIdentifier>10</SubjectSchemeIdentifier>
        <SubjectCode>JUV001000</SubjectCode>
      </Subject>
      <Audience>
        <AudienceCodeType>01</AudienceCodeType>
        <AudienceCodeValue>02</AudienceCodeValue>
      </Audience>
      <AudienceRange>
        <AudienceRangeQualifier>17</AudienceRangeQualifier>
        <AudienceRangePrecision>03</AudienceRangePrecision>
        <AudienceRangeValue>8</AudienceRangeValue>
        <AudienceRangePrecision>04</AudienceRangePrecision>
        <AudienceRangeValue>12</AudienceRangeValue>
      </AudienceRange>
    </DescriptiveDetail>
    <CollateralDetail>
      <TextContent>
        <TextType>03</TextType>
        <ContentAudience>00</ContentAudience>
        <Text textformat="02">
          <![CDATA[Something, Something, Something, Dark Side]]>
        </Text>
      </TextContent>
    </CollateralDetail>
    <PublishingDetail>
      <Imprint>
        <ImprintName>Fake Publisher</ImprintName>
      </Imprint>
      <Publisher>
        <PublishingRole>01</PublishingRole>
        <PublisherName>Fake Publisher</PublisherName>
      </Publisher>
      <PublishingStatus>02</PublishingStatus>
      <PublishingDate>
        <PublishingDateRole>01</PublishingDateRole>
        <DateFormat>00</DateFormat>
        <Date>20110701</Date>
      </PublishingDate> 
      <SalesRights>                                  
        <SalesRightsType>02</SalesRightsType>
        <Territory>                                         
          <CountriesIncluded>GB AU NZ</CountriesIncluded>
        </Territory>
      </SalesRights>
      <SalesRestriction>
        <SalesRestrictionType>04</SalesRestrictionType>
        <SalesOutlet>
          <SalesOutletIdentifier>
            <SalesOutletIDType>03</SalesOutletIDType>
            <IDValue>AMZ</IDValue>
          </SalesOutletIdentifier>
          <SalesOutletName>Amazon</SalesOutletName>
        </SalesOutlet>
        <SalesOutlet>
          <SalesOutletIdentifier>
            <SalesOutletIDType>03</SalesOutletIDType>
            <IDValue>BNO</IDValue>
          </SalesOutletIdentifier>
          <SalesOutletName>Barnes And Noble</SalesOutletName>
        </SalesOutlet>
      </SalesRestriction>
    </PublishingDetail>
    <ProductSupply>
      <SupplyDetail>
        <Supplier>
          <SupplierRole>01</SupplierRole>
          <SupplierName>Me</SupplierName>
        </Supplier>
        <ProductAvailability>20</ProductAvailability>
        <Price>                          
          <PriceAmount>12.99</PriceAmount>
          <CurrencyCode>USD</CurrencyCode>
          <Territory>
            <CountriesIncluded>GB AU NZ</CountriesIncluded>
          </Territory>
        </Price>
      </SupplyDetail>
    </ProductSupply>
  </Product>
</ONIXMessage>  

Here is some sample code to validate the above Document against the schema. To run this code you'll have to download the scheme from the link above and unzip the schema documents into the root directory of your web server. Save the above XML as a file named sample.xml; you may have to modify the file path on the cffile tag.

<cffile action="read" file="Sample.xml" variable="xmlFileResults" >
<Cfset xmlValidateResults = xmlValidate(xmlFileResults,'#cgi.http_host#/ONIX_BookProduct_3.0_reference.xsd') />
<cfdump var="#xmlValidateResults#" /><Br/><br/>

It provides this error:

[Error] :2:28: cvc-elt.1: Cannot find the declaration of element 'ONIXMessage'.

If I translate the error correctly, it cannot find the ONIXMessage tag. But, I'm rather confused as to why.

If I take a simpler XML file:

<?xml version="1.0"?>
<ONIXMessage release="3.0" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
</ONIXMessage>  

I still get the same error.

I'm trying to determine whether their is an error with the XML or the XSD or CFs validation functionality.

Has anyone seen this? Does anyone have any insight?


Based on comments, I wanted to add this:

I have no idea if this helps debug; but if I change the XML Header to reference this:

<ONIXMessage release="3.0" xmlns="http://ns.editeur.org/onix/3.0/reference"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
            xsi:schemaLocation="http://ns.editeur.org/onix/3.0/reference http://myserver/ONIX_BookProduct_3.0_reference.xsd"
            >

and remove the XSD reference from the XMLValidate() function:

<cffile action="read" file="Sample.xml" variable="xmlFileResults" >
<Cfset xmlValidateResults = xmlValidate(xmlFileResults) />
<cfdump var="#xmlValidateResults#" /><Br/><br/>

I get a slew of different errors, although they seem valid. It has no trouble finding the declaration of the ONIXMesessage; but does highlight a lot of other errors. [I'm not sure if they are valid yet or not].

Unfortunately, It is not, practical, in our environment to have to "hard code" a schema location in the XML document, though.

Was it helpful?

Solution

I was able to solve this issue. I had to do a few things.

First, the original schema made use of includes to include other files:

<xs:include schemaLocation="ONIX_BookProduct_CodeLists.xsd"/>
<xs:include schemaLocation="ONIX_XHTML_Subset.xsd"/>

I had to remove these includes and combine the three files into a single file for the validation to work. I do not know if it was an issue with the validator finding the files--due to the local path--or an issue the validation routine has with includes. Creating a single schema without the use of includes solved the issue.

I also had to add the schema location to the XML Header. This was the original:

<ONIXMessage release="3.0">

And this is the modified header:

<ONIXMessage xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" release="3.0"
             xmlns="http://ns.editeur.org/onix/3.0/reference"  
             xsi:schemaLocation="http://ns.editeur.org/onix/3.0/reference http://mydomain.com/ONIX_BookProduct_3.0_reference.xsd">

Then the validation works successfully--or at least it appears to be; I'm still getting errors but I feel they are errors in the XML documents I'm trying to validate.

<cffile action="read" file="Sample.xml" variable="xmlFileResults" >
<Cfset xmlValidateResults = xmlValidate(xmlFileResults) />
<cfdump var="#xmlValidateResults#" /><Br/><br/>

In order to prevent changes to the process creating the files; I'm using this code to add the schema information to the header "on the fly" before we perform validation:

<cfset sourceString = "<ONIXMessage ([^<>]+)?>" />
<cfset replacementString = "<ONIXMessage xmlns:xsd=""http://www.w3.org/2001/XMLSchema"" xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" release=""3.0"" xmlns=""http://ns.editeur.org/onix/3.0/reference"" xsi:schemaLocation=""http://ns.editeur.org/onix/3.0/reference #someVaraibleWithAbsoluteURLToOnixSchema#"">" />
<Cfset fileToValidate = REReplaceNoCase(fileToValidate, sourceString, replacementString ) />

Thanks to this answer for the Regex for finding an opening tag.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top