Hi so I am learning Apache Camel and trying to create a very simple service that combines two XML files based on an ID and move the resulting file to a new location. There are multiple files in a direcotry so I need to filter it based on an ID.
Client XML:
<?xml version="1.0" encoding="UTF-8"?>
<client>
<id>2</id>
<firstName>Clark</firstName>
<lastName>Kent</lastName>
<netWorth>470</netWorth>
</client>
and Address XML:
<?xml version="1.0" encoding="UTF-8"?>
<address>
<id>3</id>
<clients>
<clientId>2</clientId>
</clients>
<city>New York</city>
</address>
So I would like to add the city element from the Address XML to the Client XML.
<?xml version="1.0" encoding="UTF-8"?>
<client>
<id>2</id>
<firstName>Clark</firstName>
<lastName>Kent</lastName>
<netWorth>470</netWorth>
<city>New York</city>
</client>
I've been reading about aggregators and enrichers, from what I understand an aggregator would combine all XML files in the directory(not really what I want) and an enricher would add a resource from another service but how do I filter out based on the id and add it to the XML structure and not just at the end.
Thanks, sorry this is probably really basic I just don't know it.
I dont know , if you have resolved the issue yet , however , the answer to you question is -
Aggregator has the method in Camel , where you can implement your logic , what to do with the old exchange and new exchange. In this case , you can get the ids of 2 exchanges and match it . Once matched , you can take the unmarshalled node(city) and add it to the parent xml .
Related
I have a variable varLocationRegion and i have stored whole xml (with two elements location & region in that. Now i want to loop through that variable in xslt by matching location to get the value of region. Please advise. Thanks!
<?xml version='1.0' encoding='UTF-8'?>
<wd:Report_Data xmlns:wd="urn:com.workday/bsvc">
<wd:Report_Entry>
<wd:Location_ID>111</wd:Location_ID>
<wd:Region_Ref_ID>UNITED_STATES_REGION</wd:Region_Ref_ID>
</wd:Report_Entry>
<wd:Report_Entry>
<wd:Location_ID>111V</wd:Location_ID>
</wd:Report_Entry>
</wd:Report_Data>
Based on what information you have provided you can try out the following:
Solution for XSLT 1.0 can be tried in the following way:
Use Muenchian Grouping to group together unique Location_ID in your xml and the iterate upon the original xml using the unique Location_ID already available to find the list of associated Region_Ref_ID to particular a Location_ID.
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:wd="urn:com.workday/bsvc">
<xsl:output method="text"/>
<xsl:key name="uniqueLocation" match="wd:Report_Entry" use="wd:Location_ID"/>
<xsl:template match="/">
<!--variable called data is the variable that contains your xml-->
<xsl:variable name="uniqueLocationData" select="$data/wd:Report_Data/wd:Report_Entry[count(.|key('uniqueLocation',wd:Location_ID)[1])=1]"/>
<xsl:for-each select="$data/wd:Report_Data/wd:Report_Entry/wd:Region_Ref_ID[$data/wd:Report_Data/wd:Report_Entry/wd:Location_ID=$uniqueLocationData/wd:Location_ID]">
<xsl:value-of select="."/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
I have a product data in Solr. Solr already provides them into XML via query.
However, I need the data into different XML format (just name of xml nodes are different) for supplying them as a feeds to some other application.
Any idea, how can I do this quickly from Solr?
I finally managed to do this using one of existing response writer. This does not require writing a new response writer. Here is how I did it.
I have used XSLTResponseWriter to generate custom format xml. You can find more details here: http://wiki.apache.org/solr/XsltResponseWriter
You can find more information on how to use response writer here: https://wiki.apache.org/solr/QueryResponseWriter
Okay, now before you use it, it needs to be configured.
Step 1: Define QueryResponseWriter for XSLT in your solrconfig.xml
Add following code into your solrconfig.xml after ending your Query component.
<!--
Changes to XSLT transforms are taken into account
every xsltCacheLifetimeSeconds at most.
-->
<queryResponseWriter name="xslt" class="org.apache.solr.response.XSLTResponseWriter">
<int name="xsltCacheLifetimeSeconds">5</int>
</queryResponseWriter>
You can find its documentation at http://wiki.apache.org/solr/XsltResponseWriter
Step 2. Use proper xslt format or customize your own
You can either use existing xslt formats provided in default Solr download or use it to modify it the way you want it to work. There are 5 example formats provided already. Suppose you use example.xsl which generates a document in html with all fields, then you need to query it like this.
I customized it to use custom.xsl file format to implement my own format. I'll come to it later.
Step 3. Query your Solr using XSLT
http://localhost:8983/solr/mysolrcore/select?q=*:*&wt=xslt&tr=default.xsl&&rows=10
This will query solr and will present data in a format defined in default.xsl. Note the wt and tr parameter. You can pass how many records you want in result in rows.
Custom XML format using XSLT
Here's how I formatted my custom xml format using xslt. Hope this might be helpful to someone.
I have used example_rss.xsl as a base to start with and modified it as following.
<?xml version='1.0' encoding='UTF-8'?>
<!--
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
-->
<!--
Sample transform of Solr query results to custom XML format
-->
<xsl:stylesheet version='1.0'
xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>
<xsl:output
method="xml"
encoding="utf-8"
media-type="application/xml"
/>
<xsl:template match='/'>
<xml version="1.0">
<xsl:apply-templates select="response/result/doc"/>
</xml>
</xsl:template>
<!-- search results xslt -->
<xsl:template match="doc">
<xsl:variable name="id" select="str[#name='Id']"/>
<xsl:variable name="timestamp" select="date[#name='timestamp']"/>
<item>
<id><xsl:value-of select="int[#name='Id']"/></id>
<title><xsl:value-of select="str[#name='Name']"/></title>
<link>
http://localhost:8983/solr/mysolrcore/<xsl:value-of select="string[#name='url']"/>p-<xsl:value-of select="int[#name='Id']"/>
</link>
<image>
<xsl:value-of select="str[#name='ImageURL']"/>
</image>
<category><xsl:value-of select="arr[#name='Category']"/></category>
<availability><xsl:value-of select="bool[#name='StockAvailability']"/></availability>
<description>
<xsl:value-of select="str[#name='ShortDescription']"/>
</description>
</item>
</xsl:template>
</xsl:stylesheet>
This generates a valid xml document without the need of writing your own custom response writer.
You will have to write your own ResponseWriter
Best way is to start looking at an existing implementation. For instance CSVResponceWriter
A quick look at the code tells that you get a SolrQueryResponse object in write method. From the response you can get the searched SolrDocuments and other required information
I have a scenario where I have a productdatabase in solr and a branddatabase in MySql. In the solr productdatabase I have a field named brandid where I refer to the Mysql primary key from the branddatabase. Now I would like to join the branddatabase for each solr searchquery and groups the result seperatly from the product results. I thought about a second solr database where I save the branddata and then join it on every query, but I would like to have each brand only one time and not merged together with the product results in the same resultset. A facette-style result for the brands is my goal. Anyone has a pointer how I could achieve this kind of results in my xml/json?
The resultset how I would like to have it in pseudo solr code:
<results>
<products>
<product>
...
</product>
<product>
...
</product>
<product>
...
</product>
<product>
...
</product>
</products>
<brands>
<brand>
...
</brand>
<brand>
...
</brand>
</brands>
</results>
If you only need to serve additional fields from brand database and you do not need to search/filter on them then you could apply a simple faceting on brandid and populate the presentation fields in a post processing step from DB directly/memory cache/key value store...
and use facet.mincount=1 to eliminate the brands without any products in the current query.
Can you use a higher-level language?
I currently do something similar, but I use Java as the glue. The Java application takes in requests, goes against solr using solrj, retrieves all the results, including the facets, I take that response and query against mysql to get more information, I merge all the data in the java layer and then construct the xml/json response.
solrj
other higher-level languages are offered:
Ruby,PHP,Java,Scala,Python,.Net,Perl,Javascript
I am working in CDA documents. I am able to validate the XML documents against CDA schema and find out the the xml is CDA or not. But if it is CDA then there are two categories of CDA documents.
Structured CDA(Human readable text)
Unstructured CDA(embedded blob or referenced documents)
What is the key XML element that differentiates CDA as structured or unstructured document?
Structured document look for:
ClinicalDocument/component/structuredBody
Blob - unstructured look for:
ClinicalDocument/component/nonXmlBody
Use nonXmlBody/text to include blob or reference using the ED datatype
You can represent an unstructured document in CDA as either C-CDA (Consolidated CDA) or HITSP C62. C62 is much more commonly supported today; a quick GitHub search does not show any unstructured C-CDA implementations.
Note:the references and examples below are from non-normative specifications. You will probably need an HL7 membership to view the normative standards.
C-CDA:
From MDHT Models documentation (account required):
SHALL contain exactly one [1..1] templateId ( CONF:7710, CONF:10054 ) such that it
a. SHALL contain exactly one [1..1] #root="2.16.840.1.113883.10.20.21.1.10"
Example
<?xml version="1.0" encoding="UTF-8"?>
<ClinicalDocument xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:hl7-org:v3" xsi:schemaLocation="urn:hl7-org:v3 CDA.xsd">
<realmCode code="US"/>
<typeId root="2.16.840.1.113883.1.3"/>
<templateId root="2.16.840.1.113883.10.20.21.1.10"/>
<templateId root="2.16.840.1.113883.10.20.22.1.1"/>
<code code="18842-5" codeSystem="2.16.840.1.113883.6.1" displayName="Discharge summarization note"/>
<confidentialityCode codeSystem="2.16.840.1.113883.5.25" codeSystemName="ConfidentialityCode"/>
<custodian>
<assignedCustodian>
<representedCustodianOrganization/>
</assignedCustodian>
</custodian>
</ClinicalDocument>
HITSP C62:
From MDHT Models documentation (account required):
SHALL contain exactly one [1..1] templateId ( ) such that it
a. SHALL contain exactly one [1..1] #root="2.16.840.1.113883.3.88.11.62.1"
Example
<?xml version="1.0" encoding="UTF-8"?>
<ClinicalDocument xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:hl7-org:v3" xsi:schemaLocation="urn:hl7-org:v3 CDA.xsd">
<realmCode code="US"/>
<typeId root="2.16.840.1.113883.1.3"/>
<!-- HITSP C62 template -->
<templateId root="2.16.840.1.113883.3.88.11.62.1"/>
<!-- HL7 General Header Constraints-->
<templateId root="2.16.840.1.113883.10.20.3"/>
<!-- IHE Medical Documents -->
<templateId root="1.3.6.1.4.1.19376.1.5.3.1.1.1"/>
<!-- IHE Scanned Documents (XDS-SD) -->
<templateId root="1.3.6.1.4.1.19376.1.2.20"/>
<code code="18842-5" codeSystem="2.16.840.1.113883.6.1" displayName="Discharge summarization note"/>
<recordTarget>
<patientRole>
<patient/>
</patientRole>
</recordTarget>
</ClinicalDocument>
You can view some additional XML examples in the MDHT automated test results.
For a receiving organization to differentiate the content of an unstructured document, you should store the content type in the <code> element as shown in the examples. The content type can also be stored in the <classCode> or <typeCode> elements in an XDS submission set.
I'm using the XML data source feature in Reporting Services 2005 but having some issues with missing data. When there is no value for the first column in a row, it appears that the entire column is ignored by SSRS!
The web method request is very simple:
<Query>
<Method Name="GetIssues"
Namespace="http://www.mycompany.com/App/">
</Method>
<SoapAction>http://www.mycompany.com/App/GetIssues</SoapAction>
<ElementPath IgnoreNamespaces="true">*</ElementPath>
</Query>
Equally, the response is very simple:
<?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:Body>
<GetIssuesResponse xmlns="http://www.mycompany.com/App/">
<GetIssuesResult>
<Issue>
<Title>ABC</Title>
<RaisedBy />
<Action>Do something</Action>
</Issue>
<Issue>
<Title>ABC</Title>
<RaisedBy>Jeff Smith</RaisedBy>
<Action>Do something</Action>
</Issue>
</GetIssuesResult>
</GetIssuesResponse>
</soap:Body>
</soap:Envelope>
In this example the RaisedBy column will be completely empty. If the 'Issues' are reversed so RaisedBy first has a value, there is no problem. Any ideas?
In the Query itself, try to define your columns explicitly, instead of letting SSRS determine them for you.
In other words, where you have:
<ElementPath IgnoreNamespaces="true">*</ElementPath>
Replace the * with something like:
<ElementPath IgnoreNamespaces="true">GetIssues/GetIssuesItemsResult/listitems/data/row{#Title,#RaisedBy,#Action}</ElementPath>
Of course, that exact XPath may not be correct for your example.
Is it possible to eliminate the NULLs in the XML? Replace them with an empty string? Then you won't have to wrestle with SSRS.
If the XML is generated from a database call, that's easy enough to do (ISNULL in SQL Server).