I would like to transform a xml string (herself constructed from byte array with an external tool.
My document and my input string was all of them created with the same xsd
I read the string with pub.string:stringToBytes
then I obtain an XmlNode from pub.xml:xmlStringToXMLNode
This part works well.
I would after that create a document, call it Doc.
I call pub.xml:xmlNodeToDocument
. But the document returned is not in the correct type.
I mean that all datas are correct with correct name, but when I tried to map some data to another document, it never works.
I know it's not clear, sorry for that. So, in details, I have a simple xsd :
<?xml version="1.0" encoding="utf-8"?>
<xs:schema targetNamespace="http://tempuri.org/XMLSchema.xsd"
elementFormDefault="qualified"
xmlns="http://tempuri.org/XMLSchema.xsd"
xmlns:mstns="http://tempuri.org/XMLSchema.xsd"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
>
<xs:complexType name="EtdDaCisIUpdParty">
<xs:sequence>
<xs:element name="wUpdatetsMax">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:maxLength value="15"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="wTpsnEtendu" type="WTpsnEtendu"/>
<xs:element name="wTpsnExt" type="WTpsnExt" maxOccurs="unbounded" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="WTpsnEtendu">
<xs:sequence>
<xs:element name="Id" type="xs:string"></xs:element>
<xs:element name="Name" type="xs:string"></xs:element>
</xs:sequence>
</xs:complexType>
<xs:complexType name="WTpsnExt">
<xs:sequence>
<xs:element name="key" type="xs:string"></xs:element>
<xs:element name="value" type="xs:string"></xs:element>
</xs:sequence>
</xs:complexType>
<xs:element name="EtdDaCisIUpdParty" type="EtdDaCisIUpdParty" />
</xs:schema>
And a correspondant xml string conforming to this xsd :
<?xml version="1.0" encoding="utf-8"?>
<mstns:EtdDaCisIUpdParty xmlns:mstns="http://tempuri.org/XMLSchema.xsd" >
<mstns:wUpdatetsMax>40</mstns:wUpdatetsMax>
<mstns:wTpsnEtendu>
<mstns:Id>13</mstns:Id>
<mstns:Name>Test</mstns:Name>
</mstns:wTpsnEtendu>
<mstns:wTpsnExt>
<mstns:key>1</mstns:key>
<mstns:value>one</mstns:value>
</mstns:wTpsnExt>
<mstns:wTpsnExt>
<mstns:key>2</mstns:key>
<mstns:value>something</mstns:value>
</mstns:wTpsnExt>
<mstns:wTpsnExt>
<mstns:key>3</mstns:key>
<mstns:value>nothing</mstns:value>
</mstns:wTpsnExt>
</mstns:EtdDaCisIUpdParty>
A document generated with the same xsd :
Then I have a Flow service that transform an xml string to the document
It seems to works but it is not. If I add a simple map, it was never processed :
The pipeline in result never contains the value of the last map. After using debug mode, i understand that the resulting document of pub.xml:xmlStringToXMLNode
is not the same type of my doc.
The Id
string in the pipeline out is missing.
What's wrong with my understanding and with my example ?
The answer to your question is in the subtle differences of the mstns:EtdDaCisIUpdParty
variable's data structure between your 2nd and 3rd screenshots:
Your 2nd screenshot shows the data structure as per the document reference you used when you declared the variable, which is the design-time view of the structure (what you expect the data structure will look like):
- mstns:EtdDaCisIUpdParty
- mstns:wUpdatetsMax
- mstns:wTpsnEtendu
- ...
Versus your 3rd screenshot, which shows the actual data structure at run-time:
- mstns:EtdDaCisIUpdParty
- @version
- @encoding
- mstns:EtdDaCisIUpdParty
- mstns:wUpdatetsMax
- mstns:wTpsnEtendu
- ...
Notice the extra level in the run-time structure, which contains the XML prolog attributes @version
and @encoding
and a child document called mstns:EtdDaCisIUpdParty
representing the root node of your XML document.
Although you have declared your pipeline variable mstns:EtdDaCisUpdParty
as a document reference, at run-time that doesn't matter and has no effect. Document references let webMethods Designer show you in the GUI the data structure as you expect it to be, which makes it easier for you to work with it at design-time. However, document references are not enforced at run-time.
At run-time, because you've mapped from the top level of document
to mstns:EtdDaCisUpdParty
, it has the same structure as document
, which is different to the document reference you used at design-time. That is why your map step doesn't work. The mstns:EtdDaCisIUpdParty/mstns:wTpsnEtendu/mstns:Id
variable doesn't actually exist in the pipeline at run-time, and is instead one level deeper in the structure: mstns:EtdDaCisIUpdParty/mstns:EtdDaCisIUpdParty/mstns:wTpsnEtendu/mstns:Id
.
You can fix your Flow service by mapping from the next level down in the structure instead: document/mstns:EtdDaCisIUpdParty
--> mstns:EtdDaCisIUpdParty
, rather than document
--> mstns:EtdDaCisIUpdParty
.
Because document
is a dynamic structure (its structure is known only at run-time since it depends on the XML it parses), you will need to manually create an IData document called mstns:EtdDaCisIUpdParty
as a child underneath document
in the Service Out pipeline of the call to pub.xml:xmlNodeToDocument
, and then map from that instead:
document
in the Service Out pipeline (not the Pipeline Out on the right),mstns:EtdDaCisIUpdParty
mstns:EtdDaCisIUpdParty
in the Service Out pipeline to your variable mstns:EtdDaCisIUpdParty
in the Pipeline Out.Also, I would recommend that you set the following input parameters in your call to pub.xml:xmlNodeToDocument
, so that all XML documents are consistently parsed:
makeArrays
to false
because it is required if you specify a value for documentTypeName
nsDecls/mstns
to http://tempuri.org/XMLSchema.xsd
so that all XML documents regardless of the namespace prefix used are parsed consistently (prefixes other than mstns
will still be represented as fields called mstns:fieldname
; this won't happen unless you declare your namespaces in the nsDecls
parameter)documentTypeName
to the document reference you used to declare the variable mstns:EtdDaCisIUpdParty
so that XML elements with a maxOccurs > 1
are treated consistently (always parsed as an array even if the element in question only occurred once in the XML)And to defend against your service being called with unexpected/unsupported XML documents, you should probably invoke pub.schema:validate
to ensure the XML is well-formed and valid against the XSD you provided above, or similar.