Xproc (calabash): order of execution - xproc

I am trying to write an xproc that needs to do several p:xslt step sequentially. First, it writes two normalized XML files to disk and then a third p:xslt should take these normalized files as input.
UPDATE: first problem (third p:xslt fires before second p:store finished writing to disk) solved by adding explicit connection between second p:store and third p:xslt. (modified in code below)
UPDATE 2 Next problem is that I want to delete the temporary files with the pxf:delete instruction. This gives same order of execution problem: pxf:delete is fired before the file it is supposed to delete is written to disk.
It seems there is no p:input possible on pxf:delete. Therefore, the previous strategy of connecting the step explicitly to the last step does not seem to be possible. Any thoughts how to force pxf:delete to wait?
(Question below modified, sorry about the mess)
The xproc looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<p:declare-step type="doc:compare_files" xmlns:p="http://www.w3.org/ns/xproc" xmlns:c="http://www.w3.org/ns/xproc-step" version="1.0" xmlns:cx="http://xmlcalabash.com/ns/extensions" name="current" xmlns:doc="http://technische-documentatie.oep.overheid.nl/namespaces/doc" xmlns:pxf="http://xmlcalabash.com/ns/extensions/fileutils" >
<p:output port="result">
<p:pipe port="result" step="big_transform"/>
</p:output>
<p:option name="filename1" required="true"/>
<p:option name="filename2" required="true"/>
<p:load name="load-filename1">
<p:with-option name="href" select="$filename1"/>
</p:load>
<p:load name="load-filename2">
<p:with-option name="href" select="$filename2"/>
</p:load>
<p:xslt name="prepare_transform_1">
<p:input port="source">
<p:pipe port="result" step="load-filename1"/>
</p:input>
<p:input port="stylesheet">
<p:document href="prepare_for_hash_identity_transform.xsl"/>
</p:input>
<p:input port="parameters" kind="parameter" sequence="true">
<p:inline>
<c:param-set>
<c:param name="commentsFilteren" value="ja"/>
</c:param-set>
</p:inline>
</p:input>
</p:xslt>
<p:store href="t1.xml"/>
<p:xslt name="prepare_transform_2">
<p:input port="source">
<p:pipe port="result" step="load-filename2"/>
</p:input>
<p:input port="stylesheet">
<p:document href="prepare_for_hash_identity_transform.xsl"/>
</p:input>
<p:input port="parameters" kind="parameter" sequence="true">
<p:inline>
<c:param-set>
<c:param name="commentsFilteren" value="ja"/>
</c:param-set>
</p:inline>
</p:input>
</p:xslt>
<p:store href="t2.xml" name="store2"/>
<p:xslt name="big_transform">
<p:input port="source">
<p:pipe port="result" step="store2">
</p:input>
<p:input port="stylesheet">
<p:document href="generate_hash.xsl"/>
</p:input>
<p:input port="parameters" kind="parameter" sequence="true">
<p:inline>
<c:param-set>
<c:param name="file1" value="t1.xml"/>
<c:param name="file2" value="t2.xml"/>
</c:param-set>
</p:inline>
</p:input>
</p:xslt>
<p:import href="http://xmlcalabash.com/extension/steps/fileutils.xpl"/>
<pxf:delete href="t1.xml"/>
<pxf:delete href="t2.xml"/>
</p:declare-step>

If you perform transformations within XProc to create filename1 and filename2, then why not pass the results through themselves. Simply declare two input ports on the step, and connect the result ports of earlier transformations to the input ports of your custom step. No temp files, and no need to delete temp files.
You can of course still write intermediate results, for debugging purposes. Nothing stops you from tieing one result port to multiple input ports.
update:
Redirecting output of earlier transforms as input for parameters is done the same way as you redirect output of earlier steps to input for latter steps. The only catch is that you must conform to the syntax of parameters (c:param-set/c:param etc). So if your earlier transforms produce that syntax, then you can do this:
<?xml version="1.0" encoding="UTF-8"?>
<p:declare-step type="doc:compare_files" xmlns:p="http://www.w3.org/ns/xproc" xmlns:c="http://www.w3.org/ns/xproc-step" version="1.0" xmlns:cx="http://xmlcalabash.com/ns/extensions" name="current" xmlns:doc="http://technische-documentatie.oep.overheid.nl/namespaces/doc" xmlns:pxf="http://xmlcalabash.com/ns/extensions/fileutils" >
<p:input port="file1"/>
<p:input port="file2"/>
<p:output port="result">
<p:pipe port="result" step="big_transform"/>
</p:output>
<p:xslt name="prepare_transform_1">
<p:input port="source">
<p:pipe port="file1" step="current"/>
</p:input>
<p:input port="stylesheet">
<p:document href="prepare_for_hash_identity_transform.xsl"/>
</p:input>
<p:input port="parameters" kind="parameter" sequence="true">
<p:inline>
<c:param-set>
<c:param name="param-name" value="file1"/>
<c:param name="commentsFilteren" value="ja"/>
</c:param-set>
</p:inline>
</p:input>
</p:xslt>
<p:xslt name="prepare_transform_2">
<p:input port="source">
<p:pipe port="file2" step="current"/>
</p:input>
<p:input port="stylesheet">
<p:document href="prepare_for_hash_identity_transform.xsl"/>
</p:input>
<p:input port="parameters" kind="parameter" sequence="true">
<p:inline>
<c:param-set>
<c:param name="param-name" value="file2"/>
<c:param name="commentsFilteren" value="ja"/>
</c:param-set>
</p:inline>
</p:input>
</p:xslt>
<p:xslt name="big_transform">
<p:input port="source">
<p:pipe port="file2" step="current"/>
</p:input>
<p:input port="stylesheet">
<p:document href="generate_hash.xsl"/>
</p:input>
<p:input port="parameters" kind="parameter" sequence="true">
<p:pipe port="result" step="prepare_transform_1"/>
<p:pipe port="result" step="prepare_transform_2"/>
</p:input>
</p:xslt>
</p:declare-step>
I tested it with this command-line:
calabash --input file1=file1.xml --input file2=file2.xml --output result=out.xml test.xpl
file1.xml, and file2.xml contained dummy xml (<x/>). The prepare_for_hash_identity_transform.xsl contained:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:c="http://www.w3.org/ns/xproc-step">
<xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/>
<xsl:strip-space elements="*" />
<xsl:param name="param-name"/>
<xsl:template match="/">
<c:param-set>
<c:param name="{$param-name}" value="{base-uri(/)}"/>
</c:param-set>
</xsl:template>
</xsl:stylesheet>
The generate_hash.xsl contained:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:c="http://www.w3.org/ns/xproc-step">
<xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/>
<xsl:strip-space elements="*" />
<xsl:param name="file1"/>
<xsl:param name="file2"/>
<xsl:template match="/">
<c:param-set>
<c:param name="file1" value="{$file1}"/>
<c:param name="file2" value="{$file2}"/>
</c:param-set>
</xsl:template>
</xsl:stylesheet>
HTH!

Related

How can I get free baggage allowance with OTA_AirLowFareSearchLLS method?

I searching flights with OTA_AirLowFareSearchLLS method but he does not return free baggage allowance. How can I get infromation about free baggage allowance of itinerary segment before booking?
I can't use BFM because it was not purchased.
My OTA_AirLowFareSearchLLS RQ:
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Header>
<MessageHeader xmlns="http://www.ebxml.org/namespaces/messageHeader">
<From>
<PartyId>WebServiceClient</PartyId>
</From>
<To>
<PartyId>WebServiceSupplier</PartyId>
</To>
<CPAId>4PFI</CPAId>
<ConversationId>SWS-Test-4PFI</ConversationId>
<Service>OTA_AirLowFareSearchLLS</Service>
<Action>OTA_AirLowFareSearchLLSRQ</Action>
<MessageData>
<MessageId>9314594d-6c40-406b-9029-b887b13906b6</MessageId>
<Timestamp>2017-09-01T13:58:32Z</Timestamp>
</MessageData>
</MessageHeader>
<Security xmlns="http://schemas.xmlsoap.org/ws/2002/12/secext">
<BinarySecurityToken>
Shared/IDL:IceSess\/SessMgr:1\.0.IDL/Common/!ICESMS\/ACPCRTD!ICESMSLB\/CRT.LB!-3237262604010011257!783483!0
</BinarySecurityToken>
</Security>
</soap:Header>
<soap:Body>
<OTA_AirLowFareSearchRQ xmlns="http://webservices.sabre.com/sabreXML/2011/10"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" Version="2.3.0">
<OriginDestinationInformation RPH="1">
<FlightSegment ConnectionInd="O" DepartureDateTime="2017-10-20T00:00:00" ResBookDesigCode="Y">
<DestinationLocation LocationCode="MSQ"/>
<OriginLocation LocationCode="IEV"/>
</FlightSegment>
</OriginDestinationInformation>
<OriginDestinationInformation RPH="2">
<FlightSegment ConnectionInd="O" DepartureDateTime="2017-10-22T00:00:00" ResBookDesigCode="Y">
<DestinationLocation LocationCode="IEV"/>
<OriginLocation LocationCode="MSQ"/>
</FlightSegment>
</OriginDestinationInformation>
<PriceRequestInformation>
<OptionalQualifiers>
<PricingQualifiers CurrencyCode="UAH">
<PassengerType Code="ADT" Quantity="1"/>
</PricingQualifiers>
</OptionalQualifiers>
</PriceRequestInformation>
</OTA_AirLowFareSearchRQ>
</soap:Body>
</soap:Envelope>
This is an old service which does not return such information, BFM is actually its replacement. If you don't plan on getting that, then you can get the baggage allowance at the time of pricing the itinerary.

verify format error in HotelRateDescriptionRQ

i'm getting verify format error while searching hotel rate description using sabre soap api. my request is following:
<HotelRateDescriptionRQ xmlns="http://webservices.sabre.com/sabreXML/2011/10" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" Version="2.3.0">
<AvailRequestSegment>
<GuestCounts Count="2"/>
<HotelSearchCriteria>
<Criterion>
<HotelRef HotelCode="0039013"/>
</Criterion>
</HotelSearchCriteria>
<TimeSpan End="04-04" Start="04-01"/>
</AvailRequestSegment>
</HotelRateDescriptionRQ>
and the response is following:
<?xml version="1.0" encoding="UTF-8"?>
<soap-env:Envelope xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/"><soap-env:Header><eb:MessageHeader xmlns:eb="http://www.ebxml.org/namespaces/messageHeader" eb:version="1.0" soap-env:mustUnderstand="1"><eb:From><eb:PartyId eb:type="urn:x12.org:IO5:01">sws3-crt.cert.sabre.com</eb:PartyId></eb:From><eb:To><eb:PartyId eb:type="urn:x12.org:IO5:01">7973</eb:PartyId></eb:To><eb:CPAId>OH88</eb:CPAId><eb:ConversationId>y4JiO-0PTQn5fm5SRTPz-1459075755</eb:ConversationId><eb:Service eb:type="sabreXML"/><eb:Action>HotelRateDescriptionLLSRS</eb:Action><eb:MessageData><eb:MessageId>41ade332-41f5-4d1e-ad9a-c9b8d91a8817#176</eb:MessageId><eb:Timestamp>2016-03-27T10:50:32</eb:Timestamp></eb:MessageData></eb:MessageHeader><wsse:Security xmlns:wsse="http://schemas.xmlsoap.org/ws/2002/12/secext"><wsse:BinarySecurityToken valueType="String" EncodingType="wsse:Base64Binary">Shared/IDL:IceSess\/SessMgr:1\.0.IDL/Common/!ICESMS\/CERTG!ICESMSLB\/CRT.LB!-3422351642743054173!493550!0</wsse:BinarySecurityToken></wsse:Security></soap-env:Header><soap-env:Body><HotelRateDescriptionRS xmlns="http://webservices.sabre.com/sabreXML/2011/10" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:stl="http://services.sabre.com/STL/v01" Version="2.3.0">
<stl:ApplicationResults status="NotProcessed">
<stl:Error type="BusinessLogic" timeStamp="2016-03-27T05:50:32-05:00">
<stl:SystemSpecificResults>
<stl:Message>1VERIFY FORMAT </stl:Message>
<stl:ShortText>ERR.SWS.HOST.ERROR_IN_RESPONSE</stl:ShortText>
</stl:SystemSpecificResults>
</stl:Error>
</stl:ApplicationResults>
</HotelRateDescriptionRS></soap-env:Body></soap-env:Envelope>
so what am i doing wrong here?
look I can use HotelRateDescriptionLLSRQ using RPH atribute.
RPH atribute can be found by HotelPropertyDescriptionLLSRQ.
<soap-env:Body>
<ns:HotelRateDescriptionRQ ReturnHostCommand="false" Version="2.3.0">
<ns:AvailRequestSegment>
<ns:RatePlanCandidates>
<ns:RatePlanCandidate RPH="001" />
</ns:RatePlanCandidates>
</ns:AvailRequestSegment>
</ns:HotelRateDescriptionRQ>
</soap-env:Body>

how to tokenize a paragraph in xslt

XML
<?xml version="1.0" encoding="UTF-8"?>
<!-- Edited by XMLSpy -->
<catalog>
<example>
:20:FT13261793408907
N23B:CRED
SA32A:130918USD111670,00
</example>
</catalog>
XSLT
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:template match="/">
<xsl:for-each select="catalog">
<tr>
<td><xsl:value-of select="example"> </td>
</tr>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Current OUTPUT
:20:FT13261793408907 N23B:CRED SA32A:130918USD111670,00
Desired OUTPUT
:20:FT13261793408907
N23B:CRED
SA32A:130918USD111670,00
output must not be in a same line its must be as shown in the desired o/p
A template match should do it;
$ cat catalog.xsl
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:template match="catalog">
<xsl:value-of select="example"/>
</xsl:template>
</xsl:stylesheet>
$ xsltproc catalog.xsl catalog.xml
:20:FT13261793408907
N23B:CRED
SA32A:130918USD111670,00

How to generate doctype declarations dynamically in XProc?

Requirement:
Is to add correct Doctype declaration on the output xml [The root element of the input xml can be chapter or section element]. For Instance, consider the chapter element public identifier is PUBLIC "-//OASIS//DTD DocBook Chap XML V4.5//EN" and system identifier is "chap.dtd". Simillary for section element public identifier is PUBLIC "-//OASIS//DTD DocBook Sec XML V4.5//EN" and system identifier is "sec.dtd".
Input XML1: chapter.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook Chap XML V4.5//EN" "chap.dtd">
<chapter>
<title>Chapter Template Title</title>
<para>Text</para>
<section>
<title>Section Title</title>
<para>Section text</para>
</section>
</chapter>
Input XML2: section.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook Chap XML V4.5//EN" "chap.dtd">
<section>
<title>Section Title</title>
<para>Section text</para>
</section>
XSLT file: test.xsl:
Stylesheet just copies input xml to output and adds #sec on all section elements
Stylesheet adds correct doctype declaration to output xml, because
the input xml root element can be or element
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template name="add-doctype-declaration">
<xsl:choose>
<xsl:when test="/chapter">
<xsl:text disable-output-escaping="yes">
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook Chap XML V4.5//EN" "chap.dtd">
</xsl:text>
</xsl:when>
<xsl:when test="/section">
<xsl:text disable-output-escaping="yes">
<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook Sec XML V4.5//EN" "sec.dtd">
</xsl:text>
</xsl:when>
</xsl:choose>
</xsl:template>
<xsl:template match="/">
<xsl:call-template name="add-doctype-declaration"/>
<xsl:apply-templates/>
</xsl:template>
<!-- Identity Template -->
<xsl:template match="#*|*|processing-instruction()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="section">
<xsl:copy>
<xsl:apply-templates select="#*"/>
<xsl:attribute name="sec">
<xsl:number/>
</xsl:attribute>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Expected output.xml for Input XML1
<?xml version="1.0" encoding="utf-8"?> Input XML1:
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook Chap XML V4.5//EN" "chap.dtd">
<chapter>
<title>Chapter Template Title</title>
<para>Text</para>
<section sec="1">
<title>Section Title</title>
<para>Section text</para>
</section>
</chapter>
Expected output.xml for Input XML2
<?xml version="1.0" encoding="utf-8"?> Input XML1:
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook Sec XML V4.5//EN" "sec.dtd">
<section sec="1">
<title>Section Title</title>
<para>Section text</para>
</section>
Using any XSLT engine, the transformation works absolutely fine, and able to get the expected output
But, if the transformation is done through XProc I end up with the following error. Can someone help in resolving this error
err:XD0001 : XD0001 It is a dynamic error if a non-XML resource is produced on a step output or arrives on a step input.
XProc file: test.xpl
<?xml version="1.0" encoding="UTF-8"?>
<p:declare-step xmlns:p="http://www.w3.org/ns/xproc"
xmlns:c="http://www.w3.org/ns/xproc-step" version="1.0" name="testing">
<p:input port="source">
<p:document href="chapter.xml"/>
</p:input>
<p:output port="result">
<p:empty/>
</p:output>
<p:xslt version="1.0" name="transform">
<p:input port="stylesheet">
<p:document href="test.xsl"/>
</p:input>
<p:input port="parameters">
<p:empty/>
</p:input>
</p:xslt>
<!-- Assume that there is another transform happening for chapter/section xml -->
<p:xslt version="1.0" name="transform2">
<p:input port="stylesheet">
<p:document href="test2.xsl"/>
</p:input>
<p:input port="parameters">
<p:empty/>
</p:input>
</p:xslt>
<p:store omit-xml-declaration="false" encoding="utf-8" name="serialize">
<p:with-option name="href" select="output.xml"/>
</p:store>
</p:declare-step>
Again look at
Here is two simple examples that shows that you don't need to contextualize the Doctype generation
Section http://www.sharexml.com/x/get?k=uWn0KA7RThnt
Chapter http://www.sharexml.com/x/get?k=wAJlbUJfzIYQ
[UPDATED AFTER ANSWER]
And if you want that doctype change dynamically
Section http://www.sharexml.com/x/get?k=pBAwCds86RnQ
Chapter http://www.sharexml.com/x/get?k=JHEWghzgWIq1
Hope this helps

XML Transform for ASP.Net TreeView Control

Not being an XML expert I'm struggling with this:
I need to populate an ASP.Net Treeview control from an XML dataSource. I can usually do this no problem except on this occasion the data I've been provided with is in this format:
<Staff>
<ID>1</ID>
<Name>Boss 1</Name>
<JobTitle>Top Boss</JobTitle>
<Staff>
<ID>2</ID>
<Name>Boss 2</Name>
<JobTitle>2nd Top Boss</JobTitle>
<Staff>
<ID>3</ID>
<Name>Boss 3</Name>
<JobTitle>3rd Top Boss</JobTitle>
<Staff>
<ID>4</ID>
<Name>Worker 1</Name>
<JobTitle>Worker</JobTitle>
</Staff>
</Staff>
</Staff>
</Staff>
and I need it to be like this for the treeview control:
<Staff ID="1" Name="Boss 1" JobTitle="Top Boss">
<Staff ID="2" Name="Boss 2" JobTitle="2nd Top Boss" >
<Staff ID="3" Name="Boss 3" JobTitle="3rd Top Boss" >
<Staff ID="4" Name="Worker 1" JobTitle="Worker" ></Staff>
</Staff>
</Staff>
</Staff>
I know this should be a doddle to do with an xsl file, but I'm failing miserably. My last attempt was:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="Staff">
<Staff>
<xsl:apply-templates/>
</Staff>
</xsl:template>
<xsl:template match="Staff">
<Staff>
<xsl:for-each select="*">
<xsl:attribute name="{name()}">
<xsl:value-of select="text()"/>
</xsl:attribute>
</xsl:for-each>
</Staff>
</xsl:template>
</xsl:stylesheet>
Any ideas?
Predictably I figured it out 30mins after posting. The following converts the xml above to the required format and appears to transform any xml elements to attibutes.
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
<xsl:template match="*">
<xsl:copy>
<xsl:for-each select="#*|*[not(* or #*)]">
<xsl:attribute name="{name(.)}">
<xsl:value-of select="."/>
</xsl:attribute>
</xsl:for-each>
<xsl:apply-templates select="*[* or #*]|text()"/>
</xsl:copy>
</xsl:template>

Resources