I have practice to validation alphabet and numeric. i was can validating both of them. but the return was true or false. with fn:matches combine with escape characters regex. can anyone help me to correct my validation.
My Code
<?xml version="1.0" encoding="UTF-8"?>
<api context="/a" name="A" xmlns="http://ws.apache.org/ns/synapse">
<resource methods="POST">
<inSequence>
<property expression="json-eval($.OperationValueRegex.Value)" name="Value" scope="default" type="STRING"/>
<payloadFactory media-type="xml">
<format>
<OperationValueRegex xmlns="">
<Result1>$1</Result1>
</OperationValueRegex>
</format>
<args>
<arg evaluator="xml" expression="if($ctx:Value != '') then fn:tokenize($ctx:Value, ' ')[matches(., '^\d+$')]" xmlns:fn="http://www.w3.org/2005/xpath-functions"/>
</args>
</payloadFactory>
<respond/>
</inSequence>
<outSequence/>
<faultSequence/>
</resource>
</api>
Expected Result : when not input was not number there was new tag xml for description error
Sample Request:
{
"OperationValueRegex" : {
"Value" : "sadasdsadasd"
}
}
Result expected
<OperationValueRegex>
<Result1>sadasdsadasd</Result1>
<Status>the input not correct</Status>
</OperationValueRegex>
Thanks
For This requirement, you can use wso2 validate mediator. You can use the below json schema to validate the payload. You need to save this in the registry(use the media type as application/json).
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"OperationValueRegex": {
"type": "object",
"properties": {
"Value": {
"type": "number"
}
},
"required": [
"Value"
]
}
},
"required": [
"OperationValueRegex"
]
}
Then you can use the above json schema to validate the payload using validate mediator and construct the expected payload.
<?xml version="1.0" encoding="UTF-8"?>
<proxy xmlns="http://ws.apache.org/ns/synapse"
name="test"
startOnLoad="true"
statistics="disable"
trace="disable"
transports="http,https">
<target>
<inSequence>
<property expression="json-eval($.OperationValueRegex.Value)"
name="Value"
scope="default"
type="STRING"/>
<validate cache-schema="true">
<schema key="conf:/schema/schema.json"/>
<on-fail>
<payloadFactory media-type="xml">
<format>
<OperationValueRegex xmlns="">
<Result1>$1</Result1>
<Status>the input not correct</Status>
</OperationValueRegex>
</format>
<args>
<arg evaluator="xml" expression="$ctx:Value"/>
</args>
</payloadFactory>
<respond/>
</on-fail>
</validate>
<respond/>
</inSequence>
</target>
<description/>
</proxy>
Related
Scenario
I've integrated an external service in my API. In addition to the response from the external service, I want to add a few more JSON keys and values.
API
<?xml version="1.0" encoding="UTF-8"?>
<api context="/PhoneVerify" name="PhoneVerifi" xmlns="http://ws.apache.org/ns/synapse">
<resource methods="POST">
<inSequence>
<payloadFactory media-type="xml">
<format>
<soapenv:Envelope xmlns:cmpa="http://XXX.XXX.com" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://object.pmd.com/xsd">
<soapenv:Header/>
<soapenv:Body>
<cmpa:verify>
<!--Optional:-->
<cmpa:userName>XXXXX</cmpa:userName>
<!--Optional:-->
<cmpa:passwd>XXXXX</cmpa:passwd>
<!--Optional:-->
<cmpa:request>
<!--Optional:-->
<xsd:cnic>$1</xsd:cnic>
<!--Optional:-->
<xsd:msisdn>$2</xsd:msisdn>
<!--Optional:-->
<xsd:transactionID>$3</xsd:transactionID>
</cmpa:request>
</cmpa:verify>
</soapenv:Body>
</soapenv:Envelope>
</format>
<args>
<arg evaluator="json" expression="$.cnic"/>
<arg evaluator="json" expression="$.msisdn"/>
<arg evaluator="json" expression="$.transactionID"/>
</args>
</payloadFactory>
<log category="DEBUG" level="full"/>
<header name="Action" scope="default" value="verify"/>
<send>
<endpoint>
<address format="soap11" uri="https://XXXXX.com/CMPA/services/CnicMsisdnPairing.CnicMsisdnPairingHttpsSoap11Endpoint/">
<suspendOnFailure>
<initialDuration>-1</initialDuration>
<progressionFactor>1</progressionFactor>
</suspendOnFailure>
<markForSuspension>
<retriesBeforeSuspension>0</retriesBeforeSuspension>
</markForSuspension>
</address>
</endpoint>
</send>
</inSequence>
<outSequence>
<property name="messageType" scope="axis2" type="STRING" value="application/json"/>
<payloadFactory media-type="json">
<format>
{
"status" : "success"
"response": "$1"
}</format>
<args>
<arg evaluator="json" expression="$.verifyResponse.return"/>
</args>
</payloadFactory>
<property name="messageType" scope="axis2" type="STRING" value="application/json"/>
<respond/>
</outSequence>
<faultSequence>
<payloadFactory media-type="json">
<format>
{
"status" : "failure"
}</format>
<args/>
</payloadFactory>
</faultSequence>
</resource>
</api>
Response from External Service
"verifyResponse":{
"return" : {
"#type":"ax21:Response",
"message":"Duplicate Transaction ID",
"responseCode":"08",
"status":"00"
}
}
Desired Response
{
"status": "success"
"response": {
"#type":"ax21:Response",
"message":"Duplicate Transaction ID",
"responseCode":"08",
"status":"00"}
}
Question
My exact question is that when I try to achieve the above problem, I'm getting the response as shown below (basically its wrapped in " "). How can I make achieved the desired response?
{
"status": "success"
"response": "{"#type":"ax21:Response","message":"Duplicate Transaction ID","responseCode":"08","status":"00"}"
}
The Payload factory is adding " " since you have defined the argument $1 within " ". If you modify the Payload factory as below you should be able to get the desired output.
<payloadFactory media-type="json">
<format>
{
"status" : "success",
"response": $1
}
</format>
<args>
<arg evaluator="json" expression="$.verifyResponse.return"/>
</args>
</payloadFactory>
I have tried the above in the latest Integration Studio(8.1.0), if the above solution doesn't work please specify the MI version you are using.
Scenario
I've implemented an API which makes a soap call to external service. I need to convert the response from xml to json (which is actually happening). But somehow I'm unable to convert the nested xml nodes to json.
API
<?xml version="1.0" encoding="UTF-8"?>
<api context="/nadra" name="NadraVerification" xmlns="http://ws.apache.org/ns/synapse">
<resource methods="POST">
<inSequence>
<payloadFactory media-type="xml">
<format>
<soapenv:Envelope xmlns:nad="http://XXXX.Verification" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header/>
<soapenv:Body>
<nad:GetCitizenDemographics>
<nad:franchizeID>XXX</nad:franchizeID>
<nad:xml_request_data><![CDATA[
<CITIZEN_VERIFICATION><USER_VERIFICATION><USERNAME>XXXX</USERNAME><PASSWORD>XXXX</PASSWORD></USER_VERIFICATION><REQUEST_DATA><TRANSACTION_ID>$4</TRANSACTION_ID><SESSION_ID></SESSION_ID><CITIZEN_NUMBER>$5</CITIZEN_NUMBER><CONTACT_NUMBER>$6</CONTACT_NUMBER><AREA_NAME>$7</AREA_NAME></REQUEST_DATA></CITIZEN_VERIFICATION>
]]></nad:xml_request_data>
</nad:GetCitizenDemographics>
</soapenv:Body>
</soapenv:Envelope>
</format>
<args>
<arg evaluator="json" expression="$.transactionId"/>
<arg evaluator="json" expression="$.citizenNo"/>
<arg evaluator="json" expression="$.contactNo"/>
<arg evaluator="json" expression="$.areaName"/>
</args>
</payloadFactory>
<header name="Action" scope="default" value="http://XXXX.XXXX.XXXX/ICitizenVerification/GetCitizenDemographics"/>
<send>
<endpoint>
<address format="soap11" uri="https://verification.nadra.gov.pk/bioverisys/xml">
<suspendOnFailure>
<initialDuration>-1</initialDuration>
<progressionFactor>1</progressionFactor>
</suspendOnFailure>
<markForSuspension>
<retriesBeforeSuspension>0</retriesBeforeSuspension>
</markForSuspension>
</address>
</endpoint>
</send>
</inSequence>
<outSequence>
<property name="messageType" scope="axis2" type="STRING" value="application/json"/>
<payloadFactory media-type="json">
<format>
{
"status" : "success"
"response": $1
}</format>
<args>
<arg evaluator="json" expression="$.GetCitizenDemographicsResponse.GetCitizenDemographicsResult"/>
</args>
</payloadFactory>
<respond/>
</outSequence>
<faultSequence>
<payloadFactory media-type="json">
<format>
{
"status" : "failure"
}</format>
<args/>
</payloadFactory>
</faultSequence>
</resource>
</api>
Response from External Service after converting XML to JSON
{
"GetCitizenDemographicsResponse": {
"GetCitizenDemographicsResult": "<?xml version=\"1.0\" encoding=\"utf-16\"?>\r\n<CITIZEN_VERIFICATION xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"
xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">\r\n <RESPONSE_DATA>\r\n <RESPONSE_STATUS>\r\n <CODE>100</CODE>\r\n
<MESSAGE>successful</MESSAGE>\r\n </RESPONSE_STATUS>\r\n <SESSION_ID>00001343681312</SESSION_ID>\r\n
<CITIZEN_NUMBER>XXXX</CITIZEN_NUMBER>\r\n <PERSON_DATA>\r\n <NAME>ایوب جمال</NAME>\r\n
<FATHER_HUSBAND_NAME>XXX</FATHER_HUSBAND_NAME>\r\n <PRESENT_ADDRESS>XXXX</PRESENT_ADDRESS>\r\n
<PERMANANT_ADDRESS>XXXX</PERMANANT_ADDRESS>\r\n <DATE_OF_BIRTH>1996-01-10</DATE_OF_BIRTH>\r\n
<GENDER>male</GENDER>\r\n <EXPIRY_DATE>2030-07-11</EXPIRY_DATE>\r\n </PERSON_DATA>\r\n
</RESPONSE_DATA>\r\n</CITIZEN_VERIFICATION>"
}
}
Actual Response
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"><s:Body><GetCitizenDemographicsResponse xmlns="http://NADRA.Citizen.Verification"><GetCitizenDemographicsResult><?xml version="1.0" encoding="utf-16"?>
<CITIZEN_VERIFICATION xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<RESPONSE_DATA>
<RESPONSE_STATUS>
<CODE>107</CODE>
<MESSAGE>invalid citizen nummber</MESSAGE>
</RESPONSE_STATUS>
<SESSION_ID />
<CITIZEN_NUMBER>$5</CITIZEN_NUMBER>
</RESPONSE_DATA>
</CITIZEN_VERIFICATION></GetCitizenDemographicsResult></GetCitizenDemographicsResponse></s:Body></s:Envelope>
Question
My exact question is how can I convert the nested xml to json as well?. Since it has converted the first two xml nodes but the third xml node hasn't been converted.
Since you are using the Payload Factory to modify the response, you can use an XPath expression to extract the values from the soap endpoint. You don't need to explicitly convert the SOAP response to JSON using the messageType property before the Payload Factory.
Remove the messageType property
Use an XPath expression in the Payload Factory
Update Answer
According to the response from the backend, in the SOAP body, it has declared the <?xml version="1.0" encoding="UTF-8"?> tag before the CITIZEN_VERIFICATION element. Because of this, we need to first assign it to a property with OM type and then use it in the payload factory. Since we have a namespace defined for GetCitizenDemographicsResponse we need to add the namespace tag as well to the property mediator.
Option 1: With namespace
<property type="OM" xmlns:ns="http://NADRA.Citizen.Verification" expression="//ns:GetCitizenDemographicsResponse/*" name="Payload"/>
Or you can use local-name() function to get the value without defining the namespace in property mediator.
Option 2: Without defining the namespace
<property type="OM" expression="//*[local-name()='GetCitizenDemographicsResult']" name="Payload"/>
<outSequence>
<property type="OM" xmlns:ns="http://NADRA.Citizen.Verification" expression="//ns:GetCitizenDemographicsResponse/*" name="Payload"/>
<payloadFactory media-type="json">
<format>
{
"status" : "success",
"response": $1
}
</format>
<args>
<arg expression="$ctx:Payload" />
</args>
</payloadFactory>
<respond/>
</outSequence>
If I use a payload factory to create or simply to clean the payload in case of fault, the payload factory fail with an exception.
So, in case of error, I can't manipulate the payload.
I only need to remove it for example, so the fact that is invalid for me is not influential.
Example:
<?xml version="1.0" encoding="UTF-8"?>
<api context="/DemoError" name="DemoError" xmlns="http://ws.apache.org/ns/synapse">
<resource methods="POST">
<inSequence>
<payloadFactory media-type="json">
<format>{
"status":"OK"
}</format>
<args/>
</payloadFactory>
<loopback/>
</inSequence>
<outSequence>
<send/>
</outSequence>
<faultSequence>
<payloadFactory media-type="json">
<format>{
"status":"KO"
}</format>
<args/>
</payloadFactory>
</faultSequence>
</resource>
</api>
In this example, if I made a call with an invalid json...
The ESB, it goes in the fault sequence (right) but when I try in the fault to clean the payload, the payload factory fail (org.apache.synapse.commons.SynapseCommonsException: Existing json payload is malformed), the worst thing is that failing the fault sequence it return http 202...very bad
I'm using WSO2 EI 6.5.0
I tried out your API. It is not failing actually. If I add a <respond/> mediator after Payload Factory mediator inside Fault Sequence, I can see that the Fault Sequence payload is returning correctly.
I reproduced the issue, it's a little bit more complex.
If I have a validator, it goes in seems to go in the fault sequence, as expected, but now, the fault sequence fail on payload factory, returning http 202.
Try this:
<?xml version="1.0" encoding="UTF-8"?>
<api context="/DemoError" name="DemoError" xmlns="http://ws.apache.org/ns/synapse">
<resource methods="POST">
<inSequence>
<validate cache-schema="true">
<schema key="gov:custom/schema.json"/>
<on-fail>
<log level="custom">
<property name="ERROR" value="VALIDATE"/>
</log>
</on-fail>
</validate>
<payloadFactory media-type="json">
<format>{
"status":"OK"
}</format>
<args/>
</payloadFactory>
<loopback/>
</inSequence>
<outSequence>
<send/>
</outSequence>
<faultSequence>
<log level="custom">
<property name="ERROR" value="I'M IN FAULT SEQUENCE"/>
</log>
<property name="HTTP_SC" scope="axis2" type="STRING" value="500"/>
<payloadFactory media-type="json">
<format>{
"status":"KO"
}</format>
<args/>
</payloadFactory>
<respond/>
</faultSequence>
</resource>
</api>
with the following schema:
{
"$id": "https://example.com/person.schema.json",
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "example",
"type": "object",
"required": [ "input"],
"properties": {
"input": {
"type": "boolean",
"description": "Input"
}
}
}
and the following input:
{
"input":xxx
}
This is related to the issue reported in [1]. Until a GA release includes the fix, the WUM updated versions will contain the fix for the EI versions including wso2ei-6.6.0.
[1]. https://github.com/wso2/product-ei/issues/2757
I'm using WSO2 ESB V4.9.0 to create a proxy service for a designated end point which needs to return a transformed JSON array.
I've setup a proxy service with a foreach mediator and payloadfactory in the out sequence together with log statements to see what is happening.
The result is that each of the individual array elements is transformed as expected however the individual elements are not merged back to a single array at the end of the loop
as the documentation seems to imply. The result is that only the final element is returned.
Only thing I can see is that most of the examples I've seen don't just have an element with an array rathet than just an array. Anyone know if this is possible?
Original endpoint returns something like this:
[
{"id": "1",
"type": "object",
"name": "first",
"bounds":"[[-0.256,51.531],[-0.102,51.656]]",
"displayName": "first record"},
{"id": "2",
"type": "object",
"name": "second",
"bounds":"[[-0.256,51.531],[-0.102,51.656]]",
"displayName": "second record"},
..etc...
]
Required return from proxy service is like this:
[
{"name": "first record",
"bounds":"[[-0.256,51.531],[-0.102,51.656]]"},
{"name": "second record",
"bounds":"[[-0.256,51.531],[-0.102,51.656]]"},
..etc...
]
Actual return from proxy like this:
{"name": "first record",
"bounds":"[[-0.256,51.531],[-0.102,51.656]]"}
Configuration of the proxy is here:
<?xml version="1.0" encoding="UTF-8"?>
<proxy xmlns="http://ws.apache.org/ns/synapse"
name="newfeed_v2"
transports="https,http"
statistics="disable"
trace="disable"
startOnLoad="true">
<target>
<inSequence>
<log/>
</inSequence>
<outSequence>
<log level="full">
<property name="MESSAGE" value="FIRST"/>
</log>
<foreach id="foreach_1" expression="//jsonArray/jsonElement">
<sequence>
<payloadFactory media-type="json">
<format>{
"name" : "$1",
"bounds" : "$2"
}</format>
<args>
<arg evaluator="json" expression="$.displayName"/>
<arg evaluator="json" expression="$.bounds"/>
</args>
</payloadFactory>
<log level="full">
<property name="MESSAGE" value="ENDLOOP"/>
</log>
</sequence>
</foreach>
<log level="full">
<property name="MESSAGE" value="LAST"/>
</log>
<log/>
<send/>
</outSequence>
<endpoint>
<address uri="https://api.backend.com"/>
</endpoint>
</target>
<description/>
</proxy>
Can you try this as a workaround:
<?xml version="1.0" encoding="UTF-8"?>
<proxy xmlns="http://ws.apache.org/ns/synapse"
name="newfeed_v2"
transports="https,http"
statistics="disable"
trace="disable"
startOnLoad="true">
<target>
<inSequence>
<payloadFactory media-type="json">
<format>[
{"id": "1",
"type": "object",
"name": "first",
"bounds":"[[-0.256,51.531],[-0.102,51.656]]",
"displayName": "first record"},
{"id": "2",
"type": "object",
"name": "second",
"bounds":"[[-0.256,51.531],[-0.102,51.656]]",
"displayName": "second record"},
{"id": "4",
"type": "object",
"name": "tercero",
"bounds":"[[-0.256,51.531],[-0.102,51.656]]",
"displayName": "tercer record"}
]
</format>
<args/>
</payloadFactory>
<log level="full"/>
<loopback/>
</inSequence>
<outSequence>
<log level="full">
<property name="MESSAGE" value="FIRST"/>
</log>
<property name="Person" scope="default">
<value xmlns=""/>
</property>
<foreach id="foreach_1" expression="//jsonArray/jsonElement">
<sequence>
<payloadFactory media-type="json">
<format>{
"name" : "$1",
"bounds" : "$2"
}
</format>
<args>
<arg evaluator="json" expression="$.displayName"/>
<arg evaluator="json" expression="$.bounds"/>
</args>
</payloadFactory>
<enrich>
<source clone="true" xpath="$body//jsonObject"/>
<target action="child" xpath="$ctx:Person"/>
</enrich>
<log level="full">
<property name="MESSAGE1" value="ENDLOOP"/>
</log>
</sequence>
</foreach>
<enrich>
<source clone="true" xpath="$ctx:Person"/>
<target type="body"/>
</enrich>
<log level="full">
<property name="MESSAGE" value="ENDLOOP"/>
</log>
<!--property name="messageType" value="text/xml" scope="axis2" type="STRING"/--><log level="full">
<property name="TRANSFORMED MESSAGE" value="LAST"/>
</log>
<send/>
</outSequence>
<faultSequence/>
</target>
<description/>
</proxy>
My response:
{"value":[{"name":"first record","bounds":"[[-0.256,51.531],[-0.102,51.656]]"},{"name":"second record","bounds":"[[-0.256,51.531],[-0.102,51.656]]"},{"name":"tercer record","bounds":"[[-0.256,51.531],[-0.102,51.656]]"}]}
for each mediator will add the splitted expression to the root element so i did like this,
<api context="/foreach" name="foreach" xmlns="http://ws.apache.org/ns/synapse">
<resource methods="GET">
<inSequence>
<payloadFactory media-type="json">
<format>[
{"id": "1",
"type": "object",
"name": "first",
"bounds":"[[-0.256,51.531],[-0.102,51.656]]",
"displayName": "first record"},
{"id": "2",
"type": "object",
"name": "second",
"bounds":"[[-0.256,51.531],[-0.102,51.656]]",
"displayName": "second record"},
{"id": "4",
"type": "object",
"name": "tercero",
"bounds":"[[-0.256,51.531],[-0.102,51.656]]",
"displayName": "tercer record"}
]
</format>
<args/>
</payloadFactory>
<log level="full">
</log>
<foreach expression="//jsonArray/jsonElement">
<sequence>
<payloadFactory media-type="xml">
<format>
<result xmlns="">
<name>$1</name>
<bounds>$2</bounds>
</result>
</format>
<args>
<arg evaluator="json" expression="$.displayName"/>
<arg evaluator="json" expression="$.bounds"/>
</args>
</payloadFactory>
</sequence>
</foreach>
<property name="messageType" scope="axis2" type="STRING" value="application/json"/>
<log level="full"/>
<respond/>
</inSequence>
<outSequence>
<send/>
</outSequence>
<faultSequence/>
</resource>
</api>
and i got the response like this
{ "result": [{"name": "first record","bounds": [[-0.256,51.531],[-0.102,51.656]]},{"name": "second record","bounds": [[-0.256,51.531],[-0.102,51.656]]},{"name": "tercer record","bounds": [[-0.256,51.531],[-0.102,51.656]]}]}
We have json object as like below, Expected Result in: "(001),(011),(089),(120)".
Can anyone suggest how to iterate the json array and concat the values as mention ."(001),(011),(089),(120)"
Thanks in advance.
{
"Element": {
"Values": {
"AgentID": "aaaaa",
"TransactionData": [
{
"No": "001"
},
{
"No": "011"
},
{
"No": "089"
},
{
"No": "120"
}
]
}
}
}
You can do it by using iterate mediator, filter mediator and properties with operation scope. Try this solution. At the end you will have (001),(011),(089),(120) value in concat-data property. I have added the complete proxy for your reference.
<?xml version="1.0" encoding="UTF-8"?>
<proxy xmlns="http://ws.apache.org/ns/synapse"
name="StockQuoteProxy"
transports="https,http"
statistics="disable"
trace="disable"
startOnLoad="true">
<target>
<inSequence>
<payloadFactory media-type="json">
<format>
{
"Element": {
"Values": {
"AgentID": "aaaaa",
"TransactionData": [
{
"No": "001"
},
{
"No": "011"
},
{
"No": "089"
},
{
"No": "120"
}
]
}
}
}
</format>
<args/>
</payloadFactory>
<iterate continueParent="true"
expression="//Element/Values/TransactionData"
sequential="true">
<target>
<sequence>
<property name="data"
expression="json-eval($.TransactionData.No)"
type="STRING"/>
<filter source="boolean(get-property('operation','concat-data'))" regex="false">
<then>
<property name="concat-data"
expression="fn:concat('(',get-property('data'),')')"
scope="operation"
type="STRING"/>
</then>
<else>
<property name="concat-data"
expression="fn:concat(get-property('operation','concat-data'),',','(',get-property('data'),')')"
scope="operation"
type="STRING"/>
</else>
</filter>
</sequence>
</target>
</iterate>
<log level="custom">
<property name="con-cat-data"
expression="get-property('operation','concat-data')"/>
</log>
</inSequence>
<outSequence>
<send/>
</outSequence>
</target>
<publishWSDL uri="file:repository/samples/resources/proxy/sample_proxy_1.wsdl"/>
<description/>
</proxy>
Payload factory mediator is used only to simulate your scenario. If your client sends this JSON payload, then you don't need to have this payload factory mediator.
Filter mediator is used to omit the leading comma character. If you do not use a filter, you will get ,(001),(011),(089),(120) as a result (note the leading comma character). Of course, there can be other ways to remove leading comma character.
Refer this for more details on properties with operation scope.
For this kind of logic I sometimes favor the script mediator, as IMO it is simpler to implement things like string splicing/joining, conditional xml/json element building and so forth.