SSIS XMLSource only seeing null values in XML variable - sql-server

I have a Data Flow task with an XMLSource that references an XML Variable. The DataFlow task does recognize that there are x number of rows in the variable, but it only sees null values in every row:
The xml variable value:
<?xml version="1.0" encoding="utf-8"?>
<words>
<word>butter</word>
<word>crispy</word>
</words>
I used this source to generate the XSD within the XMLSource Editor - here is the auto-generated XSD:
<?xml version="1.0"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="words">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="unbounded" name="word" type="xs:string" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
The package compiles, executes, and processes all the rows in my XML, but only sees nulls rather than the actual text strings... Here is a shot of the DataViewer displaying 2 rows after reading the XML variable:

I discovered a way to get the values to populate... I'll post it here without giving myself points, in case anyone else encounters the same problem. This is just a "how to fix", but I'll give credit to anyone who can explain the "deeper whys".
Essentially, the XML needed to be wrapped in another root node:
<?xml version="1.0" encoding="utf-8"?>
<datarows>
<words>
<word>bacon</word>
<word>roasted</word>
<word>pork</word>
<word>edamame</word>
</words>
</datarows>
Even though the original XML I used was valid, SSIS wanted it to be wrapped in an additional root node, which I named datarows. Once I did that the package recognized the word values and completed successfully.
The associated schema:
<?xml version="1.0"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="datarows">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="1" name="words">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="unbounded" name="word" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>

I too had the same problem,. I was trying to consume a web service and import the output xml into a table in sql 2008.
The issue is really with the namespace that gets generated in the output xml by the webservice. The trick I have used was
1. Stored the output of the web service in a package level variable
2. Add a 'script task', to replace the unwanted name space.
3. Then used 'XMl Source Task' to import the data into a table.
-Kris...

Related

XML schema using int with pattern failing validation

I have an XSD schema with a nonNegativeInteger type that is restricted with a pattern (\d{2}) and try to validate an XML file, but get error 6937:
XML Validation: The canonical form of the value '01' is not valid according to the specified type. This can result from the use of pattern facets on non-string types or range restrictions or enumerations on floating-point types. Location: /*:xy[1]/*:Item1[1]/*:Field1[1]
CREATE XML SCHEMA COLLECTION dbo.XY_SCHEMA
AS'
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
<xs:simpleType name="Int_Abs_02">
<xs:restriction base="xs:nonNegativeInteger">
<xs:minInclusive value="01"/>
<xs:maxInclusive value="99"/>
<xs:pattern value="\d{2}"/>
</xs:restriction>
</xs:simpleType>
<xs:complexType name="Item1">
<xs:sequence>
<xs:element name="Field1">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="Int_Abs_02"/>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
<xs:element name="xy">
<xs:complexType>
<xs:sequence>
<xs:element name="Item1" type="Item1"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>';
GO
DECLARE #xy XML(dbo.XY_SCHEMA)
SELECT #xy = '
<xy xsi:noNamespaceSchemaLocation="XY" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Item1>
<Field1>01</Field1>
</Item1>
</xy>'
I guess the canonical form is '1' which then is not using the given pattern?
I have read the MS documentation regarding Canonical Forms and Pattern Restrictions.
Is there any way I can make this work without changing the XML or XSD?
I'm using SQL Server 2014.
This is legal according to the XSD spec, but it makes life very difficult and is best avoided. If you want the value "01" to be valid, but "1" to be invalid, then in all probability the value you are dealing with is not really an integer at all, but a string made up of digits. (Compare phone numbers, where leading zeros are significant, and arithmetic is meaningless).
If it really is a number, for example a day of the month, then it's best to allow the leading zero to be omitted. If it isn't a number, but is some kind of code, then it's best to define it as a string that matches a regex.

XSD for XML with 1 elementname on 2 locations in

Introduction
Here below there are 2 very simplified versions of xml documents in a XML column on a SQL Server 2014 production server.
To start solving performances issues with this XML field I have created an XSD.
Issue to resolve
One issue is left over (see examples below):
- An element with the name "ProjectNr"
- is Always unique within a specific XML document
- But can be found on one of 2 different locations
Question
My question is two-folded:
- Can this issue be solved
- And if so, how?
XML documents
XML document, type 1:
<Project>
<ID>1</ID>
<Name>1</Name>
<ProjectNr>1</ProjectNr>
</Project><br/><br/>
XML document, type 2:
<Project>
<ProjectNr>1</ProjectNr>
<ID>1</ID>
<Name>1</Name>
</Project>
The all compositor allows some flexibility in the ordering, and ensures that each element occurs with the desired amount of occurrences.
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified">
<xs:element name="Project">
<xs:complexType>
<xs:all>
<xs:element name="ProjectNr" type="xs:string"/>
<xs:element name="ID" type="xs:string"/>
<xs:element name="Name" type="xs:string"/>
</xs:all>
</xs:complexType>
</xs:element>
</xs:schema>
Both documents are valid against the above schema (assuming the two <br/> in the question are typos, because document 1 would otherwise not be wellformed).

Does providing an XML Schema collection for a Stored Procedure work with WCF-SQL Send Port?

Consider the following simplified XML schema collection
CREATE XML SCHEMA COLLECTION CD.AcceptMessageSchema AS '
<xs:schema xmlns="http://schemas.microsoft.com/Sql/2008/05/Procedures/Submit"
xmlns:ns1="http://schemas.microsoft.com/Sql/2008/05/Procedures/Submit"
xmlns:b="http://schemas.microsoft.com/BizTalk/2003"
targetNamespace="http://schemas.microsoft.com/Sql/2008/05/Procedures/Submit"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified">
<xs:element name="AcceptMessage">
<xs:complexType>
<xs:sequence>
<xs:element name="MessagePayload" type="xs:string"/>
<xs:element name="PatientIdentifiers">
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="unbounded" minOccurs="0" name="ID" type="ID">
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
and the following Stored Procedure definition
create procedureSubmit.AcceptMessage_DEV #AcceptMessage xml(CD.AcceptMessageSchema)
as
Insert into blah...
...stored proc guts go here...
You'll notice that the single paramter is defined associated to the Schema Collection. My assumption was that given the association to the SchemaCollection, you would be able to call the Stored Procedure by sending in something like the following:
<AcceptMessage xmlns="http://schemas.microsoft.com/Sql/2008/05/Procedures/Submit" xmlns:biztalk="http://InteriorHealth.BizTalk.CDX.Schemas.SQLSubmit.AcceptMessage" xmlns:ns0="http://microsoft.com/HealthCare/HL7/2X" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<MessagePayload>
<![CDATA[somepayloaddata]]>
</MessagePayload>
<PatientIdentifiers>
<ID OID="2.16.840.1.113883.4.50" Value="3454545" AssigningAuthorityName="Patient Health Number" />
<ID OID="2.16.840.1.113883.3.277.1.73" Value="4545454" AssigningAuthorityName="Patient EMR Number" />
</PatientIdentifiers>
</AcceptMessage>
and it would work over a WCF-SQL send port.
The strange this is, if I call the stored procedure in SSMS:
EXEC Submit.AcceptMessage #AcceptMessage = ' <AcceptMessage xmlns="http://schemas.microsoft.com/Sql/2008/05/Procedures/Submit" xmlns:biztalk="http://InteriorHealth.BizTalk.CDX.Schemas.SQLSubmit.AcceptMessage" xmlns:ns0="http://microsoft.com/HealthCare/HL7/2X" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<MessagePayload>
<![CDATA[somepayloaddata]]>
</MessagePayload>
<PatientIdentifiers>
<ID OID="2.16.840.1.113883.4.50" Value="3454545" AssigningAuthorityName="Patient Health Number" />
<ID OID="2.16.840.1.113883.3.277.1.73" Value="4545454" AssigningAuthorityName="Patient EMR Number" />
</PatientIdentifiers>
</AcceptMessage>';
it works just fine, but sending it over the wire via WCF-SQL I get the error:
The start element with name "MessagePayload" and namespace "http://schemas.microsoft.com/Sql/2008/05/Procedures/Submit" was unexpected. Please ensure that your input XML conforms to the schema for the operation.
This is the same thing that would happen before I applied the XML Scheam collection and defined the stored proc like this:
create procedureSubmit.AcceptMessage_DEV
#MessagePayload xml,
#PatientIdentifiers xml
as
If I were to then send in a request like above, it would give the error:
The start element with name "ID" and namespace "http://schemas.microsoft.com/Sql/2008/05/Procedures/Submit" was unexpected. Please ensure that your input XML conforms to the schema for the operation.
Because it didn't know what to do with the <ID> elements inside the <PatientIdentifiers> element.
I previously was wrapping all parameter data in CDATA tags and it worked, but I wanted the added schema validation if it would work.
So does this mean that when calling WCF-SQL, I basically have to CDATA everything inside the parameter elements, or is there something I'm missing?
Also, this is a messaging-only solution, no orchestrations.
How can I send nested XML into a SQL Stored proc in order to parse it and insert the data into tables?
In this specific case, I think a Table Value Parameter would be easier.
However, to answer what I think is your underlying question, you can pass an XML Type parameter either as CDATA or escaped Xml. The WCF Schema Element Type will always be xs:string though.
You are generating a schema for the SP, correct? You don't actually say.

Defining an XSD so that XML element will be type="array"

My question relates to defining an XSD document. My specific issue is how to define the XSD so that when the XML is generated an element will have type="array".
Desired result would be something like:
<names type="array">
<name>
......
</name>
</names>
I have experimented using methods recommended on several forums, but from I have found it seems to me like there may not even be a type for array, which confuses me since a resulting XML element can have a type of array.
There are tools that will take an XSD and generate a sample XML document that adheres to the XSD, but you should understand that the primary purpose of an XSD is to validate an XML document.
This XSD will validate your XML document:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="names">
<xs:complexType>
<xs:sequence>
<xs:element name="name" maxOccurs="unbounded"/>
</xs:sequence>
<xs:attribute name="type"/>
</xs:complexType>
</xs:element>
</xs:schema>
Note also that using a type="array" attribute-value pair is unconventional in the XML as type information is conveyed in the XSD in the content model for names and needn't be repeated explicitly in the XML document.

Apache Camel Enricher

Hi so I am learning Apache Camel and trying to create a very simple service that combines two XML files based on an ID and move the resulting file to a new location. There are multiple files in a direcotry so I need to filter it based on an ID.
Client XML:
<?xml version="1.0" encoding="UTF-8"?>
<client>
<id>2</id>
<firstName>Clark</firstName>
<lastName>Kent</lastName>
<netWorth>470</netWorth>
</client>
and Address XML:
<?xml version="1.0" encoding="UTF-8"?>
<address>
<id>3</id>
<clients>
<clientId>2</clientId>
</clients>
<city>New York</city>
</address>
So I would like to add the city element from the Address XML to the Client XML.
<?xml version="1.0" encoding="UTF-8"?>
<client>
<id>2</id>
<firstName>Clark</firstName>
<lastName>Kent</lastName>
<netWorth>470</netWorth>
<city>New York</city>
</client>
I've been reading about aggregators and enrichers, from what I understand an aggregator would combine all XML files in the directory(not really what I want) and an enricher would add a resource from another service but how do I filter out based on the id and add it to the XML structure and not just at the end.
Thanks, sorry this is probably really basic I just don't know it.
I dont know , if you have resolved the issue yet , however , the answer to you question is -
Aggregator has the method in Camel , where you can implement your logic , what to do with the old exchange and new exchange. In this case , you can get the ids of 2 exchanges and match it . Once matched , you can take the unmarshalled node(city) and add it to the parent xml .

Resources