I have an integration object with this XML representation:
<root>
<request code="123" title="Test">
<user name="Chuck Bartowski" email="-" />
<data d1="aaa" d2="bbb" d3="ccc" />
<attachments>
<attachment name="text.txt" size="50" />
<attachment name="image.png" size="385" />
</attachments>
</request>
</root>
And I need to merge some of the nodes (integration components) into one, to convert the XML into something like this:
<root>
<request code="123" title="Test" userName="Chuck Bartowski" userEmail="-"
data1="aaa" data2="bbb" data3="ccc" />
<attachments>
<attachment name="text.txt" size="50" />
<attachment name="image.png" size="385" />
</attachments>
</request>
</root>
I'm trying to achieve this using Siebel 7.8 data mappings (EAI Data Transformation Engine). So, I have created an integration object map, with the following integration component maps:
NAME SOURCE IC TARGET IC
r1 request -> request
r2 user -> request
r3 data -> request
att attachment -> attachment
Unfortunately, it's not doing what I was expecting. Instead, it outputs this:
<root>
<request code="123" title="Test">
<attachments>...</attachments>
</request>
<request userName="Chuck Bartowski" userEmail="-">
<attachments>...</attachments>
</request>
<request data1="aaa" data2="bbb" data3="ccc">
<attachments>...</attachments>
</request>
</root>
I know it's possible to map a single source component into multiple targets, but, can the opposite be done? Can I merge many sources into a single target?
So far, I've tried setting the Parent Component Map Name field to r1, in both r2 and r3, but it only earned me a nice SBL-EAI-04008 error: Integration component type 'request' is not a valid child type for component type 'request'.
Am I missing some configuration step, or is this just impossible to do using only the data mapping engine? I'm calling it from a server script, so if nothing else works, I could just adapt the property set there after the mapping finishes.
I found the answer in the Siebel bookshelf. Yes, it can be done, but not how I was trying to do it:
You may want to address fields in components other than the source component. This is because your target component may depend on more than one component in the source object. In such cases, you cannot use different component maps with different source components, and the same target component, because each component map creates a different instance of the target component. Data Mapping Engine expressions allow you to use the dot notation to address fields, other than the source component, in source integration object components —for example, [Component Name.Field Name].
Addressing fields in other components is legal only if the cardinality of the component is less than or equal to one relative to the source component —that is, only if the component can be uniquely identified from the context of the source component without using any qualifiers other than the component name.
So, the key is to create only one component mapping for each target, and then include field mappings from the other sources. In my example, I would have:
NAME SOURCE IC TARGET IC
req request -> request
att attachment -> attachment
And inside req, the following field mappings:
SOURCE TARGET
[code] -> code
[title] -> title
[user.name] -> userName
[user.email] -> userEmail
[data.d1] -> data1
...
Related
In XSLT 2.0 I am transforming a tei-xml document into HTML. In that transformationI need content from another document: I want to copy/transform a small set of nodes from the second document into the HTML output.
While processing the principal tei document I get the id and assign it to a variable:
<xsl:variable name="licenseid" select="./replace(#corresp,'#','')"/>
Then I go out to the other document and fetch the node using the variable, with the returned node assigned to a variable:
<xsl:variable name="licenseloc" select="doc(concat($somepath,'includes_sourcedesc.xml'))//tei:list[#type='copyright_type']/tei:item[#xml:id=$licenseid]"/>
This node I obtain looks like this:
<list type="copyright_type">
<item xml:id="copyright-cc-by-nc-sa-4.0">
<desc xml:lang="en">This work is made by available the author under the
<ref target="http://creativecommons.org/licenses/by-nc-sa/4.0/">Creative Commons Attribution-NonCommercial-ShareAlike
4.0 International License</ref>.</desc>
</item>
</list>
And I want to transform it (from desc) to this:
<span>This work is made by available by the author under the
<a href="http://creativecommons.org/licenses/by-nc-sa/4.0/">Creative Commons Attribution-NonCommercial-ShareAlike
4.0 International License</a>.</span>
If this were in my 'current' tei document I would handle it through templates, but I'm unsure how to copy and transform the nested layers from within a different 'current' document.
I have developed a template design in JasperSoft Studio and upload jrxml file to JasperServer. I want to send data (JSON or XML) to filling report template from my python application and take back report in some popular formats like PDF, XLS using REST API. I do not want to store the data on the server. How can I do this? Or data must be stored on the server and there is no alternative way of their transmission by WEB-Service?
The data does not necessarily have to reside on the server.
You could design your template in such way that you can pass the data via input control parameters as #tobi6 suggested.
Then you could use either the reports service or the reportExecutions service to get the desired output.
In your case, the data could be the actual data(XML or JSON) or the source of the data(a URL to the data file).
Here are some basic samples for working with XML data(for JSON is quite similar):
With actual data as parameter
The JasperReports template:
<?xml version="1.0" encoding="UTF-8"?>
<!-- Created with Jaspersoft Studio version 6.1.1.final using JasperReports Library version 6.1.1 -->
<!-- 2016-05-25T14:18:00 -->
<jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports http://jasperreports.sourceforge.net/xsd/jasperreport.xsd" name="XmlDSReport_with_data" pageWidth="595" pageHeight="842" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" uuid="85d7b9ad-6feb-43dc-84cc-5175bf629546">
<parameter name="xmlString" class="java.lang.String">
<defaultValueExpression><![CDATA["<?xml version=\"1.0\" encoding=\"UTF-8\"?><a><b><val>val1</val></b><b><val>val2</val></b></a>"]]></defaultValueExpression>
</parameter>
<parameter name="XML_INPUT_STREAM" class="java.io.InputStream">
<defaultValueExpression><![CDATA[new java.io.ByteArrayInputStream($P{xmlString}.getBytes("UTF-8"))]]></defaultValueExpression>
</parameter>
<queryString language="xPath">
<![CDATA[/a/b]]>
</queryString>
<field name="value" class="java.lang.String">
<fieldDescription><![CDATA[val]]></fieldDescription>
</field>
<columnHeader>
<band height="31" splitType="Stretch">
<staticText>
<reportElement x="150" y="0" width="100" height="30" uuid="b33a123d-8987-4da4-b21b-1f9ccc50e92d"/>
<text><![CDATA[value]]></text>
</staticText>
</band>
</columnHeader>
<detail>
<band height="30" splitType="Stretch">
<textField>
<reportElement x="150" y="0" width="100" height="30" uuid="14c51219-5ce2-47ce-abb9-71bc11a6f28c"/>
<textFieldExpression><![CDATA[$F{value}]]></textFieldExpression>
</textField>
</band>
</detail>
</jasperReport>
After you deploy the report and create the input control for the xmlString parameter you can test it. Let's say you want to pass this XML instead of leaving the default in place:
<?xml version="1.0" encoding="UTF-8"?>
<a>
<b><val>new_val1</val></b>
<b><val>new_val2</val></b>
</a>
To test the reports service you run something similar to this in a terminal(I URL-encoded the XML string) and check the result:
curl -u user:password \
http://localhost:8080/jasperserver/rest_v2/reports/reports/XmlDSReport_with_data.pdf?xmlString=%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22UTF-8%22%3F%3E%0A%20%20%20%20%3Ca%3E%0A%20%20%20%20%20%20%3Cb%3E%3Cval%3Enew_val1%3C%2Fval%3E%3C%2Fb%3E%0A%20%20%20%20%20%20%3Cb%3E%3Cval%3Enew_val2%3C%2Fval%3E%3C%2Fb%3E%0A%20%20%20%20%3C%2Fa%3E > report.pdf
To test the reportExecutions service, the main steps are:
1.Create an XML file with the request(name it reportExecutionRequest.xml)
<reportExecutionRequest>
<reportUnitUri>/reports/XmlDSReport_with_data</reportUnitUri>
<outputFormat>pdf</outputFormat>
<freshData>true</freshData>
<saveDataSnapshot>false</saveDataSnapshot>
<interactive>true</interactive>
<allowInlineScripts>true</allowInlineScripts>
<async>false</async>
<parameters>
<reportParameter name="xmlString">
<value><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<a><b><val>new_val1</val></b><b><val>new_val2</val></b></a>]]></value>
</reportParameter>
</parameters>
</reportExecutionRequest>
2.Make the request(you need to save the session cookie to retrieve the output):
curl -u user:password \
-H "Content-Type: application/xml" \
-d #reportExecutionRequest.xml \
-c cookies.txt \
http://localhost:8080/jasperserver/rest_v2/reportExecutions
3.Get the output with the requestID and exportID from the result of the previous request:
curl -b cookies.txt \
http://localhost:8080/jasperserver/rest_v2/reportExecutions/cc57b351-cfb6-429e-8c92-d0aebebbed66/exports/b71d6353-1eec-4304-8713-5d0f3105680e/outputResource > report.pdf
With data as source URL
It is the same report template, but with the two parameters replaced with:
<parameter name="xmlSource" class="java.lang.String">
<defaultValueExpression><![CDATA["http://serverwithdata/xmlData.xml"]]></defaultValueExpression>
</parameter>
<parameter name="net.sf.jasperreports.xml.source" class="java.lang.String">
<defaultValueExpression><![CDATA[$P{xmlSource}]]></defaultValueExpression>
</parameter>
Note: I created two parameters here just because I wanted to keep a shorter name for the parameter when passing it through the reports service. I also created an input control just for the xmlSource parameter.
The tests in this case are similar.
EDIT: To use JSON instead of XML, the original JasperReports template needs to be adjusted in this way:
For data as parameter, just change the xmlString parameter, the XML_INPUT_STREAM parameter and the queryString to this:
<parameter name="jsonString" class="java.lang.String">
<defaultValueExpression><![CDATA["{\"a\": [ {\"b\": { \"val\": \"val1\"}}, {\"b\": { \"val\": \"val2\" }}]}"]]></defaultValueExpression>
</parameter>
<parameter name="JSON_INPUT_STREAM" class="java.io.InputStream">
<defaultValueExpression><![CDATA[new java.io.ByteArrayInputStream($P{jsonString}.getBytes("UTF-8"))]]></defaultValueExpression>
</parameter>
<queryString language="json">
<![CDATA[a.b]]>
</queryString>
For data as source URL, change the xmlString parameter, the XML_INPUT_STREAM parameter and the queryString to this:
<parameter name="jsonSource" class="java.lang.String">
<defaultValueExpression><![CDATA["http://serverwithdata/jsonData.json"]]></defaultValueExpression>
</parameter>
<parameter name="net.sf.jasperreports.json.source" class="java.lang.String">
<defaultValueExpression><![CDATA[$P{jsonSource}]]></defaultValueExpression>
</parameter>
<queryString language="json">
<![CDATA[a.b]]>
</queryString>
The cURL tests for the REST services are basically the same with the main difference that you will be passing JSON instead of XML and use the JSON specific parameters jsonString or jsonSource.
The API is separated in three domains:
Administration services
Repository services
Report services
To generate reports, they first have to be deployed to the server via the repository service. If later on the report needs to be generated, it is called via the report services. Here, it is also possible to start synchronous or asynchronous report generation.
Therefore the report needs to be in the repository.
EDIT
Since you also need to deliver parameters, referring to this example it would work like this:
Add a report parameter
Add a input control for a report parameter
Call the API with your input parameter: http://<host>:<port>/jasperserver[-pro]/rest_v2/reports/reports/samples/EmployeeAccounts.html?EmployeeID=sarah_id
Do as needed for other parameters
I am trying to pass parameters during an XSLT transformation. Here is the xsl stylesheet.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:param name="param1" select="'defaultval1'" />
<xsl:param name="param2" select="'defaultval2'" />
<xsl:template match="/">
<xslttest>
<tagg param1="{$param1}"><xsl:value-of select="$param2" /></tagg>
</xslttest>
</xsl:template>
</xsl:stylesheet>
The following in the java code.
File xsltFile = new File("template.xsl");
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document stylesheet = builder.parse("template.xsl");
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer xsltTransformer = transformerFactory.newTransformer(new DOMSource(stylesheet));
//Transformer xsltTransformer = transformerFactory.newTransformer(new StreamSource(xsltFile));
xsltTransformer.setParameter("param1", "value1");
xsltTransformer.setParameter("param2", "value2");
StreamResult result = new StreamResult(System.out);
xsltTransformer.transform(new DOMSource(builder.newDocument()), result);
I get following errors:-
ERROR: 'Variable or parameter 'param1' is undefined.'
FATAL ERROR: 'Could not compile stylesheet'
However, if i use the following line to create the transformer everything works fine.
Transformer xsltTransformer = transformerFactory.newTransformer(new StreamSource(xsltFile));
Q1. I just wanted to know whats wrong in using a DOMSource in creating a Transformer.
Q2. Is this one of the ideal ways to substitute values for placeholders in an xml document? If my placeholders were in a source xml document is there any (straightforward) way to substitute them using style sheets (and passing parameters)?
Q1: This is a namespace awareness problem. You need to make the DocumentBuilderFactory namespace aware:
factory.setNamespaceAware(true);
Q2: There are several ways to get the values from an external xml file. One way to do this is with the document function and a top level variable in the document:
<!-- Loads a map relative to the template. -->
<xsl:variable name="map" select="document('map.xml')"/>
Then you can select the values out of the map. For instance, if map.xml was defined as:
<?xml version="1.0" encoding="UTF-8"?>
<mappings>
<mapping key="value1">value2</mapping>
</mappings>
You could remove the second parameter from your template, then look up the value using this line:
<tagg param1="{$param1}"><xsl:value-of select="$map/mappings/mapping[#key=$param1]"/></tagg>
Be aware that using relative document URIs will require that the stylesheet has a system id specified, so you will need to update the way you create your DOMSource:
DOMSource source = new DOMSource();
source.setNode(stylesheet);
source.setSystemId(xsltFile.toURL().toString());
In general, I suggest looking at all of the options that are available in Java's XML APIs. Assume that all of the features available are set wrong for what you are trying to do. I also suggest reading the XML Information Set. That specification will give you all of the definitions that the API authors are using.
I have a database with an xml document in it, and I want to display a transformed xml on my xforms page, when the submission is sent (I'm using orbeon forms).
My solution is, that on the submission my servlet gets the xml from the database, writes it into a file, xslt transforms the xml tree (when and how should I do the transformation?), but I don't know, how to display this file on the xforms page. Maybe the replace="instance" attribute in can help, but i don't know how.
Thanks!
Now, after Alessandro's advice, Im trying to use this xpl thing, but it doesn't work.
In the model:
<xforms:insert nodeset="instance('inst2')"
origin="xxforms:call-xpl('oxf:/resources/pipeline.xpl', 'data',
instance('inst1'), 'data')"/>
in pipeline.xpl:
<p:config xmlns:p="http://www.orbeon.com/oxf/pipeline"
xmlns:oxf="http://www.orbeon.com/oxf/processors">
<p:param type="input" name="data"/>
<p:param type="output" name="data"/>
<p:processor name="oxf:xslt">
<p:input name="data" href="#data"/>
<p:input name="config" href="transform.xsl"/>
<p:output name="data" ref="data"/>
</p:processor>
My instance, that I want to transform is "complaint-instance", the transformed instance called "trf-instance", the pipeline.xpl file is in the same directory with my xforms page. My styesheet called customerToOperator.xsl. What's wrong in my code?
I just noticed, the note: "If you are using separate deployment, the service and XSLT transformation must be present in the Orbeon WAR file, instead of within your application."
Ehm... Where should I put these files?
my app in details:
a) an xforms page, with 2 instances:
<instance id='inst1'>
<name>
<lastname/>
<firstname/>
</name>
</instance>
<instance id='inst2'>
<fname>
<fullname/>
</fname>
</instance>
I got 2 input fields, referenced on name/lastname and name/firstname.
I have an xforms:insert node, described above, and an xforms:submission node:
<xforms:submission
id="save-submission"
ref="instance('inst2')"
action="/my-servlet"
method="post"
replace="none">
I added 2 files to orbeon/WEB-INF/resources, the pipeline.xpl, (described above) and transform.xsl:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/">
<fname>
<fullname>
<xsl:value-of select="name/firstname"/>
<xsl:value-of select="name/lastname"/>
</fullname>
</fname>
</xsl:template>
</xsl:stylesheet>
And I have a servlet, which writes the posted instance on the console (now it writes inst2 on the console, but without the user input data, only the nodes...)
A really need to fix this...
Thanks again!
To get the XML from a database (relational or not) and apply a transformation, instead of writing my own servlet, I would use an XPL pipeline, and map this pipeline to a URL through the page flow. Now you have a service that answers to an HTTP request and returns XML. To call the service from XForms, you use an <xforms:submission replace="instance">. You end up with the XML in an instance, and you can display it with something like: <xforms:output value="saxon:serialize(instance(), 'xml')"/>.
In all cases (including separate deployment), the pipeline and XSLT file must be in the "resources". Usually, this means the WEB-INF/resources of the Orbeon's web app. But you can also do more fancy things by setting up the Orbeon resource manager to also use other directories on disk.
I have a custom definition for a document library and I am trying to rename documents within the library using only the out of the box web services. Having defined a view with the "Name" field supplied and trying the "LinkFilename", my calls to rename a file are respectively returning a failure or ignoring the new value.
How do I rename a file using the SharePoint web services?
Use the Lists.UpdateListItems web method. The XML request should look like:
<Batch OnError="Continue" PreCalc="TRUE" ListVersion="0">
<Method ID="1" Cmd="Update">
<!-- List item ID of document -->
<Field Name="ID">2</Field>
<!-- Full URL to document -->
<Field Name="FileRef">http://Server/FullUrl/File.doc</Field>
<!-- New filename -->
<Field Name="BaseName">NewName</Field>
</Method>
</Batch>
You should be able to use UpdateListItems. Here's an example.
Per comment: So the actual question is "how do I call a web service?" Take a look a this example. Some more good walkthroughs here.