URL rewrite using Datapower Gateway - url

I'm trying to setup a URL rewrite using datapower. A request will come in from the customer in the following format - /products/{productid}/balance the {productid} will change for each customer and I need to change the format to be /balance/products/{productid} so that I don't need multiple context roots in Websphere. I have setup a MPGW but I am unable to put in the correct variables to change the request above which is supposed to be written in Perl (which I don't know) Can anyone help please?

If I got it correctly, ou need to create Policy with Request-Rule wich will contain XSL-transformation like this:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:dp="http://www.datapower.com/extensions"
extension-element-prefixes="dp"
exclude-result-prefixes="dp" >
<xsl:template match="/">
<xsl:variable name="originalUrl" select="dp:variable('var://service/URI')"/>
<xsl:variable name="productId" select="substring-before(substring-after($originalUrl, '/products/'), '/balance')"/>
<xsl:variable name="modifiedUrl" select="concat('/balance/products/', $productId)"/>
<!--Set your own destination host ofc-->
<dp:set-variable name="'var://service/routing-url'" value="concat('http://127.0.0.1', $modifiedUrl)"/>
</xsl:template>
</xsl:stylesheet>
var://service/URI is a readonly service variable which contains URL-path from HTTP request
var://service/routing-url is a writable service variable wich contains a URI for routing

Related

XSLT pipeline : Error XPDY0002 - The context item for axis step fn:root(...)/element() is absent

Please, I need some help dealing with saxon api :)
I create a pipeline with 2 XsltTransform of the same xslt and when i run transform i get this error :
2019-01-24 11:32:15,673 [pool-2-thread-1] INFO e.s.e.x.XsltListener - file
2019-01-24 11:32:15,674 [pool-2-thread-1] INFO e.s.e.x.XsltListener - Error
XPDY0002 while evaluating xsl:message content: The context item for axis
step fn:root(...)/element() is absent
here is my xslt :
<xsl:stylesheet exclude-result-prefixes="#all" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:variable name="supp" as="xs:string" select="root()/*/name()"/>
<xsl:template match="/">
<xsl:message select="$supp"/>
<file/>
</xsl:template>
the first XsltTransform work fine but It seems that i have no context node during the second XstTransform running.
I use :
transformer1.setSource(source) : source is a SAXSource
transformer1.setDestination(transformr2)
transformr2.setDestination(serialiser)
According to documentation (XsltTransform.setInitialContextNode):
This value is ignored in the case where the XsltTransformer is used as the Destination of another process. In that case the initial context node will always be the document node of the document that is being streamed to this destination.
Thanks for your Help
In general in XSLT 3 you need to distinguish between the initial match selection https://www.w3.org/TR/xslt-30/#dt-initial-match-selection which is used to decide which template to apply first and the global context item https://www.w3.org/TR/xslt-30/#dt-global-context-item that is used to evaluate global parameters and variables. I think you seem to expect that in your second stylesheet the result of your first acts as both but it seems, at least in your setup, Saxon does not assume that but only sets your initial match selection to the result of the first stylesheet. So try moving the <xsl:variable name="supp" as="xs:string" select="root()/*/name()"/> into the template e.g.
<xsl:template match="/">
<xsl:variable name="supp" as="xs:string" select="root()/*/name()"/>
<xsl:message select="$supp"/>
<file/>
</xsl:template>
I am not sure there is another way, at least in the case of chaining two streaming transformations you can't the second stylesheet expect to have access to the whole result tree of the first to be used to evaluate global parameters or variables.

xpath expression to select specific xml nodes that are available in a file

I was trying to find the out a way for my strange problem.
How to write an xpath to select specific xml nodes that are available in another text file.
For Instance,
<xsl:for-each select="SUBSCRIBER_PROFILE_LIST/SUBSCRIBER_PROFILE_INFO[GROUP_NAME eq (group name list in a text file as input)]">
For example,
<xsl:for-each select="SUBSCRIBER_PROFILE_LIST/SUBSCRIBER_PROFILE_INFO[GROUP_NAME eq collection('select_nodes.txt')]">
select_nodes.txt contains list of string that can be selected only
For example
ABC
IJK
<SUBSCRIBER>
<MSISDN>123456</MSISDN>
<SUBSCRIBER_PROFILE_LIST>
<SUBSCRIBER_PROFILE_INFO>
<PROFILE_MSISDN>12345</PROFILE_MSISDN>
<GROUP_NAME>ABC</GROUP_NAME>
<GROUP_ID>18</GROUP_ID>
</SUBSCRIBER_PROFILE_INFO>
<SUBSCRIBER_PROFILE_INFO>
<PROFILE_MSISDN>456778</PROFILE_MSISDN>
<GROUP_NAME>DEF</GROUP_NAME>
<GROUP_ID>100</GROUP_ID>
</SUBSCRIBER_PROFILE_INFO>
<SUBSCRIBER_PROFILE_INFO>
<PROFILE_MSISDN>78876</PROFILE_MSISDN>
<GROUP_NAME>IJK</GROUP_NAME>
<GROUP_ID>3</GROUP_ID>
</SUBSCRIBER_PROFILE_INFO>
</SUBSCRIBER>
XSLT2 has limited functionality for parsing arbitrary text files. I would suggest:
Make the select_nodes.txt an XML file and load it using the doc() function:
<xsl:variable name="group_names" as="xs:string *"
select="doc('select_nodes.xml')/groups/group"/>
with select_nodes.xml looking like this:
<?xml version="1.0" encoding="UTF-8"?>
<groups>
<group>ABC</group>
<group>IJK</group>
</groups>
Pass the group names as a stylesheet parameter. (How you do this depends on which XSLT engine you're using and whether it's through the command line or an API.) If it's through an API, then you may be able to pass the values in directly as xs:string-typed objects. Otherwise you'll have to parse the parameter:
<xsl:param name="group_names_param"/>
<!-- Assuming the input string is a whitespace-separated list of names -->
<xsl:variable name="group_names" as="xs:string *"
select="tokenize($group_names_param, '\s+')"/>
In either case your for-each expression would then look like this:
<xsl:for-each select="
SUBSCRIBER_PROFILE_LIST/SUBSCRIBER_PROFILE_INFO[GROUP_NAME = $group_names]">
<!-- Do something -->
</xsl:for-each>

XSLT: How to access elements of type both namespace and without namespaces within same article

Please suggest to access the elements which are not having any namespaces. However my code able to access and alter the nodes (elements) which are having namespaces. I am using XSLT2 version. Find my xml (I used DTD path mapped to my local path, please suggest also for access the XML without DTD help.
InPut XML:
<!DOCTYPE article PUBLIC "-//ES//DTD journal article DTD version 5.2.0//EN//XML" "D:/DTDs/Els-parser/art520.dtd">
<article>
<fm>
<ce:title>The title</ce:title>
<ce:author-group>
<ce:author><ce:surname>Rudramuni</ce:surname><ce:given-names>TP</ce:given-names></ce:author>
</ce:author-group>
</fm>
<body>
<ce:sections>
<ce:section>
<ce:section-title>The first Head</ce:section-title>
<ce:para>Tha first para</ce:para>
</ce:section>
</ce:sections>
</body>
<back>
<ref><ce:author>Vijay</ce:author></ref>
</back>
</article>
XSLT:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ce="http://www.elsevier.com/xml/common/dtd"
xmlns:sb="http://www.elsevier.com/xml/common/struct-bib/dtd"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:mml="http://www.w3.org/1998/Math/MathML"
version='2.0'>
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="fm">
<xsl:element name="ce:front"><xsl:apply-templates/></xsl:element>
</xsl:template>
<xsl:template match="ce:author">
<xsl:element name="name"><xsl:apply-templates/></xsl:element>
</xsl:template>
</xsl:stylesheet>
Required Result:
<?xml version="1.0" encoding="UTF-8"?>
<article>
<ce:front>
<ce:title>The title</ce:title>
<ce:author-group><name><ce:surname>Rudramuni</ce:surname><ce:given-names>TP</ce:given-names></name></ce:author-group>
</ce:front>
<body><ce:sections><ce:section><ce:section-title>The first Head</ce:section-title><ce:para>Tha first para</ce:para></ce:section></ce:sections></body>
<back>
<ref><name>Vijay</name></ref>
</back>
</article>
But I am getting some extra namespaces like "xmlns="http://www.elsevier.com/xml/ja/dtd" and xmlns="", and some extra attributes are found for some elements like view="all". Thanks in advance. Please suggest.
You seem to ask a lot of questions on XSLT 2.0 recently, which is ok of course, but please kindly consider these guidelines when asking questions:
Use valid examples that we can reproduce your problem with. Your examples, in this and other questions, are not well-formed (missing namespaces in this question for instance), which makes it hard to help you (and they will downvote or close your question, see How to ask).
Tone down the examples to the bare minimum, otherwise people will not run to help you as it is too hard to understand the question asked. In this case, a two-line XML and XSLT would explain your issue.
Run the code you paste here and copy the output (or errors) you get. In this question for instance, the output is not namespace-well-formed, which cannot possibly be the output of any XSLT processor.
To answer your question, you can use a wild-card NameTest, which selects that name in any namespace:
select="*:something"
select="*:foo/*:bar"
select="*:foo[contains(., #*:some-attr)]"

how to decode base64Binary-to-string in xslt

Hi I am trying to convert my Base64 data to string in xslt but unable to do so.
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="2.0"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:saxon="http://saxon.sf.net/">
<xsl:template match="Data">
<xsl:element name="fos1">
<xsl:value-of select="(saxon:base64Binary-to-string(
xs:base64Binary("Data"),
"UTF8"))"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
I have one xml file also where i have stored base64 data the looks like below code
<?xml version="1.0" encoding="UTF-8"?>
<Data>e1xydGYxXGZiaWRpc1xhbnNpXGFuc2ljcGcxMjUyXGRlZmYwXGRlZmxhbmcxMDMxXGRlZmxhbmdmZTEwMzFcZGVmdGFiNzA4e1xmb250dGJse1xmMFxmc3dpc3NcZnBycTJcZmNoYXJzZXQwIFZlcmRhbmE7fX0NClx2aWV3a2luZDRcdWMxXHBhcmRcbHRycGFyXGxhbmcyMDU3XGJcZjBcZnMyMCBGYXJlIFJ1bGVzXHBhcg0KXGIwXHBhcg0KXHBhcg0KXGIgUmVib29raW5nc1xwYXINClxwYXJkXGx0cnBhclxxalxiMCBCb29raW5nIGNoYW5nZXMgYWxsb3dlZCwgdXAgdG8gMzAgbWludXRlcyBwcmlvciB0byBkZXBhcnR1cmUsIGZvciBhIGZlZSBvZiBcYiBFVVIgNjAgLyBDSEYgNzkgLyBHQlAgNTQgLyBVU0QgODMgLyBDWksgMTY4MCAvIFNFSyA2MDAgLyBOT0sgNDkyIC8gUExOIDI3NiAvIEhVRiAxOTgwMFxiMCAgcGVyIHBlcnNvbiBhbmQgbGVnLCB3aGVyZSBhcHBsaWNhYmxlIHBsdXMgZGlmZmVyZW5jZSB0byBhY3R1YWwgZmxpZ2h0IGZhcmUuIENoYW5nZSBvZiB0YXJpZmYgb25seSBhbGxvd2VkIGludG8gbmV4dCBoaWdoZXIgY2F0ZWdvcnkgaWYgaW5pdGlhbCB0YXJpZmYgbm90IGF2YWlsYWJsZS4gSUYgVEhFIE5FVyBGQVJFIElTIExPV0VSIFRIQU4gVEhFIE9SR0lOQUwgT05FLCBOTyBSRUZVTkQgV0lMTCBCRSBHUkFOVEVELlxwYXINClxwYXINClxwYXJkXGx0cnBhclxiIENhbmNlbGxhdGlvbnNccGFyDQpcYjAgQ2FuY2VsbGF0aW9ucyBhcmUgbm90IGFsbG93ZWQuIEZhcmUgaXMgbm9uIHJlZnVuZGFibGUuIElOIENBU0UgT0YgTk9TSE9XLCBQQVggTVVTVCBQVVJDSEFTRSBBTiBFTlRJUkVMWSBORVcgVElDS0VUIC8gT1JJR0lOQUwgUEFJRCBBTU9VTlQgV0lMTCBOT1QgQkUgUkVGVU5ERUQvQ1JFRElURUQuXHBhcg0KXHBhcg0KXGIgTmFtZSBDaGFuZ2VzXHBhcg0KXGIwIE5hbWUgY2hhbmdlcyBhbGxvd2VkLCB1cCB0byAzMCBtaW51dGVzIHByaW9yIHRvIGRlcGFydHVyZSwgZm9yIGEgZmVlIG9mIFxiIEVVUiA2MCAvIENIRiA3OSAvIEdCUCA1NCAvIFVTRCA4MyAvIENaSyAxNjgwIC8gU0VLIDYwMCAvIE5PSyA0OTIgLyBQTE4gMjc2IC8gSFVGIDE5ODAwIFxiMCBwZXIgcGVyc29uIGFuZCBib29raW5nLCB3aGVyZSBhcHBsaWNhYmxlIHBsdXMgZGlmZmVyZW5jZSB0byBhY3R1YWwgZmxpZ2h0IGZhcmUuXHBhcg0KXHBhcg0KXGIgQ2hlY2tlZCBMdWdnYWdlXHBhcg0KXGIwIENoZWNrZWQgbHVnZ2FnZSBvcHRpb25hbCwgc3RhbmRhcmQgYWRkaXRpb25hbCBjb3N0cyBhcHBseS5ccGFyDQpcYiBBVFROISBTbWFydDpcYjAgIE9uZSBwaWVjZSBvZiBjaGVja2VkIGx1Z2dhZ2UgaXMgYXV0b21hdGljYWxseSBpbmNsdWRlZCBwZXIgcGVyc29uICh0b3RhbCB3ZWlnaHQgMjMga2cpLCBmb3IgZnVydGhlciBwaWVjZXMgYW5kIGV4Y2VzcyBsdWdnYWdlLCBzdGFuZGFyZCBhZGRpdGlvbmFsIGNvc3RzIGFwcGx5LlxwYXINClxwYXINClxiIFNlYXRpbmdccGFyDQpcYjAgT3B0aW9uYWwsIHN0YW5kYXJkIGFkZGl0aW9uYWwgY29zdHMgYXBwbHkuXHBhcg0KXGIgQVRUTiEgU21hcnQ6IFxiMCBTZWF0IHJlc2VydmF0aW9uIGlzIGluY2x1ZGVkIHBlciBQZXJzb24sIGFsc28gbW9yZSBsZWdyb29tIHNlYXQgKGlmIGF2YWlsYWJsZSlcYlxwYXINClxiMFxwYXINClxiIE1pbGVzXHBhcg0KXGIwIEluY2x1ZGluZyBtaWxlc1xwYXINClxwYXINClxiIE1lYWxccGFyDQpcYjAgTm90IGluY2x1ZGVkXHBhcg0KXGIgQVRUTiEgU21hcnQ6IFxiMCBTbmFjayBhbmQgZHJpbmsgaW5jbHVkZWRccGFyDQpccGFyDQpccGFyDQpcYiBBVFROISEgRm9yIEJsaW5kIEJvb2tpbmcgRmFyZXMgYW5kIEJvb21lcmFuZyBSZXdhcmQgZmxpZ2h0cyB0aGUgcGFydGljdWxhciBjb25kaXRpb25zIGFjY29yZGluZyB0byBHZXJtYW53aW5ncyBHQ0MgYXBwbHkuXHBhcg0KXHBhcg0KfQ0K</Data>
The call xs:base64Binary("Data") tries to create a base-64 value from the character string "Data", which is not a legal base-64 string. So you should be getting an error message saying roughly that. Hmm. You didn't mention an error message; you didn't explain what exactly you mean by "unable to do so". Next time, provide more information, ok?
If you want to apply the function to the string value of the Data element, bear in mind that you are making the call in an expression located in a template which matches that element. You almost certainly want to replace the call in the current expression with something like xs:base64Binary(.).

How to Use DataSource Property in DataFormWebPart

I'm writing a custom web part that extends DataFormWebPart.
public class MyCustomWebPart : DataFormWebPart{
// other methods
public override void DataBind()
{
XmlDataSource source =
new XmlDataSource() { Data = #"
<Person>
<name cap='true'>Bryan</name>
<occupation>student</occupation>
</Person>
"
};
DataSources.Add(source);
base.DataBind();
}
}
The only noticeable thing I do is overriding the DataBind() method, where I use xml as the data source.
After I deploy the web part, I set the following XSL to it:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/">
<xmp>
<xsl:copy-of select="*"/>
</xmp>
</xsl:template>
</xsl:stylesheet>
This xsl will surround the input xml with a tag . So I expected the web part to display the original xml data as I wrote in C# code behind. But what shows up in the web part is this:
<Person>
<name cap="true" />
<occupation />
</Person>
All the values within the inner-most tags disappear.
What's going on? Can anybody help me?
Thanks.
I know this is several months since your question but I also experienced this same issue and have found the resolution.
On this MSDN forum post - http://social.msdn.microsoft.com/forums/en-US/sharepointdevelopment/thread/0a0527b6-3a05-4791-8cc5-9a6de07d23f3
they mentioned that there is a bug in the xsmldatasource xpath navigation binding, and the resolution is to override the GetXPathNavigator method.
moving code from the databind to this method immediately resolved the lookup issue.

Resources