How to create document from Xml string
I would like to convert an xml string (it was built from a byte array with an external tool.
My document and my input line were generated from the same xsd I read the line with pub.string:stringToBytes
then I get the XmlNode frompub.xml:xmlStringToXMLNode
This part works well.
I would create a document after that, call it Doc. I'm calling pub.xml:xmlNodeToDocument
. But the returned document is not of the correct type. I mean all the data is correct with the correct name, but when I tried to map some data against another document, it never works.
I know this is not clear, sorry about that. So, in detail, 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 the corresponding xml line corresponding 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>
Document generated with the same xsd:
Then I have a stream service that converts the xml string to document
Seems to work, but it doesn't. If I add a simple map, it never gets processed:
The resulting pipeline never contains the last card value. After using debug mode, I realize that the resulting document is pub.xml:xmlStringToXMLNode
not the same type as my document.
The Id
line is missing in the pipeline.
What is wrong with my understanding and my example?
source to share
The answer to your question lies in the subtle differences in variable structure mstns:EtdDaCisIUpdParty
between your 2nd and 3rd screenshots:
Your second screenshot shows the data structure according to the doc link you used when you declared a variable that is a representation of the project time structure (as you expect the data structure will look like):
- mstns:EtdDaCisIUpdParty
- mstns:wUpdatetsMax
- mstns:wTpsnEtendu
- ...
Compared to the third screenshot which shows the actual data structure at runtime:
- mstns:EtdDaCisIUpdParty - @version - @encoding - mstns:EtdDaCisIUpdParty - mstns:wUpdatetsMax - mstns:wTpsnEtendu - ...
Notice the extra layer in the runtime structure that contains the XML prologue attributes @version
and a @encoding
named child document mstns:EtdDaCisIUpdParty
that represents the root node of your XML document.
Although you have specified your pipeline variable mstns:EtdDaCisUpdParty
as a document reference, this is irrelevant at runtime and has no effect. Document links allow webMethods Designer to show you the data structure as you expect in a graphical interface, allowing you to work with it at design time. However, links to documentation are not executed at runtime.
At run time, since you are mapped from the top level document
to mstns:EtdDaCisUpdParty
, it has the same structure as the one document
, which is different from the document reference you used during design time. This is why your map step is not working. The variable mstns:EtdDaCisIUpdParty/mstns:wTpsnEtendu/mstns:Id
does not actually exist in the pipeline at run time, and at one level deeper in the structure: mstns:EtdDaCisIUpdParty/mstns:EtdDaCisIUpdParty/mstns:wTpsnEtendu/mstns:Id
.
You can fix their service flow, comparing it to the next level in the structure: document/mstns:EtdDaCisIUpdParty
→ mstns:EtdDaCisIUpdParty
, rather than document
→ mstns:EtdDaCisIUpdParty
.
Since it document
is a dynamic structure (its structure is only known at runtime, since it depends on the XML it parses), you need to manually create an IData document named mstns:EtdDaCisIUpdParty
as a child under the Call Service Exitdocument
in the pipeline , and then type:pub.xml:xmlNodeToDocument
- Right click on the Service Outlet
document
in the pipeline (not the Pipeline Out on the right), - Insert new document variable
- Name it
mstns:EtdDaCisIUpdParty
- Open
mstns:EtdDaCisIUpdParty
in the pipeline Service output to your variablemstns:EtdDaCisIUpdParty
in Pipeline Out .
Additionally, I would recommend that you set the following input parameters when invoked pub.xml:xmlNodeToDocument
so that all XML documents are parsed sequentially:
- Set
makeArrays
tofalse
because it is necessary if you supply a value fordocumentTypeName
- Set
nsDecls/mstns
tohttp://tempuri.org/XMLSchema.xsd
so that all XML documents regardless of the namespace prefix used are parsed sequentially (prefixes other thanmstns
will still be represented asmstns:fieldname
namespaced fields ; this will not happen unless you declare namespaces in the parameternsDecls
) - Set
documentTypeName
the document reference you used to declare the variablemstns:EtdDaCisIUpdParty
so that the XML elements with aremaxOccurs > 1
parsed sequentially (always parsed as an array, even if the element in question happened only once in the XML)
And to protect your service from unexpected / unsupported XML documents, you should probably call pub.schema:validate
to make sure the XML is well-formed and valid against the XSD you listed above or similar.
source to share