How can I transform an incoming SOAP response into a JSON document using WSO2 ESB - esb

I would like to convert json to xml using ESB4.10. And need to know and find out how does JBoss ESB support JSON http request? If this has to be done using the HTTP Request do share some thread that I can use to implement this.

Within your proxy or REST API element, if you are willing to convert the given response (SOAP) back to JSON just simply include the following properties in your out sequence:
<xslt key="ns-remove"/>
<property name="messageType" value="application/json" scope="axis2"/>
Include this section in registry, some generally we need to remove any namespaces available.
<localEntry key="ns-remove">
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml"/>
<xsl:template match="*">
<xsl:element name="{local-name()}">
<xsl:apply-templates select="#*"/>
<xsl:apply-templates select="node()"/>
</xsl:element>
</xsl:template>
<xsl:template match="#*">
<xsl:attribute name="{local-name()}">
<xsl:value-of select="."/>
</xsl:attribute>
</xsl:template>
<xsl:template match="/">
<xsl:copy>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<xsl:template match="comment() | processing-instruction() | text()">
<xsl:copy/>
</xsl:template>
</xsl:stylesheet>
</localEntry>

Related

Applying redactions in the form of string substitutions to HTML documents using XSLT

I have a large number of HTML (and possibly other xml) documents that I need to redact.
The redactions are typically of the form "John Doe" -> "[Person A]". The text to be redacted may be in headers or paragraphs, but will almost always be in paragraphs.
Simple string substitutions really. Not very complicated things.
However, I do want to preserve document structure, and I would prefer to not reinvent any wheels. String substitution in the document text may do the job, but also may break document structure, so it will be a last option.
Right now I have stared at XSLT for an hour and tried to force "str:replace" to do my bidding. I will spare you from viewing me feeble attempts that didn't work, but I will ask this: Is there a simple and know way to apply my redactions using XSLT, and could you post it here?
Thank you in advance.
Update: at the request of Martin Honnen I'm adding my input files, as well as the command I used to get the latest error message. From this it will be apparent that I'm a complete n00b when it comes to XSLT :-)
.html file:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
<title>TodaysDate</title>
<meta name="created" content="2020-11-04T30:45:00"/>
</head>
<body>
<ol start="2">
<li><p> John Doe on 9. fux 2057 together with Henry
Fluebottom formed the company Doe &; Fluebottom Widgets
Inc. </p>
</ol>
</body>
</html>
The XSLT transformation file:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>
<xsl:template match="p">
<xsl:copy>
<xsl:attribute name="matchesPattern">
<xsl:copy-of select='str:replace("John Doe", ".*", "[Person A]")'/>
</xsl:attribute>
<xsl:copy-of select='str:replace("Henry Fluebottom", ".*", "[Person B]")'/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
The command and the output:
$ xsltproc -html transform.xsl example.html
xmlXPathCompOpEval: function replace bound to undefined prefix str
xmlXPathCompiledEval: 2 objects left on the stack.
<?xml version="1.0"?>
TodaysDate
<p matchesPattern=""/>
$
xsltproc is based on libxslt and that way supports various EXSLT functions like str:replace, to use it you will need to declare the namespace
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:str="http://exslt.org/strings"
exclude-result-prefixes="str"
version="1.0">
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="p//text()">
<xsl:value-of select="str:replace(., 'John Doe', '[Person A]')"/>
</xsl:template>
</xsl:stylesheet>
There is no simple way in XSLT 1.0 to perform multiple replacements on the same string. You need to use a recursive named template, performing one replacement operation at a time, then moving to the next instance of the current find string or - when no next instance exists - to the next find/replace pair.
Consider the following example:
Input
<html>
<head>
<title>John Doe and Henry Fluebottom</title>
</head>
<body>
<p>John Doe is a person. John Doe on 9. fux 2057 together with Henry Fluebottom formed the company Doe & Fluebottom Widgets Inc. Henry Fluebottom is also a person.</p>
</body>
</html>
XSLT 1.0 (+ EXSLT node-set() function)
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common"
extension-element-prefixes="exsl">
<xsl:output method="xml" omit-xml-declaration="yes" version="1.0" encoding="utf-8" indent="yes"/>
<!-- identity transform -->
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:variable name="dictionary">
<entry find="John Doe" replace="[Person A]"/>
<entry find="Henry Fluebottom" replace="[Person B]"/>
</xsl:variable>
<xsl:template match="text()">
<xsl:call-template name="multi-replace">
<xsl:with-param name="string" select="normalize-space(.)"/>
<xsl:with-param name="entries" select="exsl:node-set($dictionary)/entry"/>"/>
</xsl:call-template>
</xsl:template>
<xsl:template name="multi-replace">
<xsl:param name="string"/>
<xsl:param name="entries"/>
<xsl:choose>
<xsl:when test="$entries">
<xsl:call-template name="multi-replace">
<xsl:with-param name="string">
<xsl:call-template name="replace">
<xsl:with-param name="string" select="$string"/>
<xsl:with-param name="search-string" select="$entries[1]/#find"/>
<xsl:with-param name="replace-string" select="$entries[1]/#replace"/>
</xsl:call-template>
</xsl:with-param>
<xsl:with-param name="entries" select="$entries[position() > 1]"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$string"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="replace">
<xsl:param name="string"/>
<xsl:param name="search-string"/>
<xsl:param name="replace-string"/>
<xsl:choose>
<xsl:when test="contains($string, $search-string)">
<xsl:value-of select="substring-before($string, $search-string)"/>
<xsl:value-of select="$replace-string"/>
<xsl:call-template name="replace">
<xsl:with-param name="string" select="substring-after($string, $search-string)"/>
<xsl:with-param name="search-string" select="$search-string"/>
<xsl:with-param name="replace-string" select="$replace-string"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$string"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
Result
<html>
<head>
<title>[Person A] and [Person B]</title>
</head>
<body>
<p>[Person A] is a person. [Person A] on 9. fux 2057 together with [Person B] formed the company Doe & Fluebottom Widgets Inc. [Person B] is also a person.</p>
</body>
</html>
As you can see, this replaces all instances of the search strings anywhere in the input document (except for attributes), while preserving the document's structure.
Note that the input in your example does not actually contain the "Henry Fluebottom" search string. You might want to get around that by calling the first template with:
<xsl:with-param name="string" select="normalize-space(.)"/>
instead of:
<xsl:with-param name="string" select="."/>
The first problem is to find an XSLT processor that actually supports string replacement. The replace() function is standard in XSLT 2.0+, but does not exist in XSLT 1.0. Some XSLT 1.0 processors support an extension function str:replace() in a different namespace, but at the very least, you need to add the namespace declaration xmlns:str="http://exslt.org/strings" to your stylesheet in order to locate the function. I don't know if that will work (I don't know if there is any way of using this function with xsltproc); my advice would be to use an XSLT 2.0+ processor instead.
The next problem is the way you are invoking the function. Typically, a correct invocation would be
replace(., "John Doe", "[Person A]")
though you will have to jump through a few more hoops to make multiple replacements on the same string.
I've no idea what you are trying to achieve with the <xsl:attribute name="matchesPattern"> instruction.

Select Parent Node without Child node. XSLT

I would like to select Parent node without Child node.
Example:
<Shop>
<Product>
<ProductId>1</ProductId>
<Description>ProductList</Description>
<Milk>
<MilkId></MilkId>
</Milk>
</Product>
</Shop>
Desired Output:
<Shop>
<Product>
<ProductId>1</ProductId>
<Description>ProductList</Description>
</Product>
</Shop>
I tried below XSLT but it failed to return correct result:
<xsl:copy-of select="//Product/not[Milk]"/>
Thank you for any help.
Update:
XSLT:
<xsl:copy-of select="Product/*[not(self::Milk)]" />
Returns:
<ProductId>1</ProductId>
I need below structure to be returned:
<Shop>
<Product>
<ProductId>1</ProductId>
<Description>ProductList</Description>
</Product>
</Shop>
You can use a variant of the Identity template:
<!-- Identity template variant -->
<xsl:template match="node()|#*">
<xsl:copy>
<xsl:apply-templates select="node()[local-name()!='Milk']|#*" />
</xsl:copy>
</xsl:template>
Or, as a more XSLT-2.0 way suggested in the comments
<xsl:template match="node()|#*">
<xsl:copy>
<xsl:apply-templates select="node() except Milk|#*" />
</xsl:copy>
</xsl:template>
It copies all nodes except for the ones named Milk and its children.
If you want to apply this only to Product nodes, you also have to use the Identity template and change the matching rule to
<xsl:template match="Product">...
A solution using only xsl:copy-of could be copying the Product element and then copy all of its children (except for the Milk ones) with
<xsl:copy-of select="Product/*[not(self::Milk)]" />
Or, in a whole XSLT-2.0 template
<xsl:template match="//Product">
<xsl:copy>
<xsl:copy-of select="* except Milk" />
</xsl:copy>
</xsl:template>
A whole XSLT-1.0 stylesheet could look like
<?xml version="1.0" ?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<!-- Identity template -->
<xsl:template match="node()|#*">
<xsl:copy>
<xsl:apply-templates select="node()|#*" />
</xsl:copy>
</xsl:template>
<xsl:template match="Product">
<xsl:copy>
<xsl:copy-of select="*[not(self::Milk)]" />
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Its output is:
<?xml version="1.0"?>
<Shop>
<Product>
<ProductId>1</ProductId>
<Description>ProductList</Description>
</Product>
</Shop>

How to change the format of XML schema I get from SQL server

I have a query:
SELECT top 0 * FROM sometable FOR XML AUTO, ELEMENTS, XMLSCHEMA ('MyURI')
This query returns a schema:
<xsd:element name="ClientName">
<xsd:simpleType>
<xsd:restriction base="sqltypes:nvarchar" sqltypes:localeId="1033" sqltypes:sqlCompareOptions="IgnoreCase IgnoreKanaType IgnoreWidth" sqltypes:sqlSortId="52">
<xsd:maxLength value="50" />
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
but I want something more like this:
<xsd:element name="ClientName">
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:maxLength value="50" />
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
How can I achieve this?
You can use a XSL transform to change the SQL Server types back to the desired XSD types.
How apply the transform depends on your application. If you are creating static schemata for your tables, then you can use something like Visual Studio or msxsl. If this is a routine request from the server, then Applying an XSL Transformation (SQLXML Managed Classes) may be a better fit.
A style sheet you can build on with additional types is:
<?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"
xmlns:sqltypes="http://schemas.microsoft.com/sqlserver/2004/sqltypes"
xmlns="http://www.w3.org/1999/XSL/Transform"
>
<xsl:output method="xml" indent="yes"/>
<xsl:param name="Strip">false</xsl:param>
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="#base">
<xsl:attribute name="{name()}">
<xsl:choose>
<xsl:when test=".='sqltypes:nvarchar'">xsd:string</xsl:when>
<!-- Add additional tests here -->
<xsl:otherwise>
<xsl:value-of select="."/>
</xsl:otherwise>
</xsl:choose>
</xsl:attribute>
</xsl:template>
<xsl:template match="#sqltypes:*">
<xsl:if test="$Strip=true">
<xsl:comment>
<xsl:text>Stripped (</xsl:text>
<xsl:value-of select="concat(name(), '="', ., '"')"/>
<xsl:text>)</xsl:text>
</xsl:comment>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
Change the Strip parameter at the beginning to false if you need to see the attributes that are stripped in the transformation process.

Pass XSL template output to XSL function

I am using XSLTJSON to convert my XML to JSON. My raw XML is not in the format that I want, so I first pass it through an XSL stylesheet to clean it up and then pass the output of that stylesheet into XSLTJSON.
Right now I'm doing this by calling transformers serially. I'd like to streamline it and have only one call to the transformer necessary. Is there a way to write an XSL stylesheet that includes json.xsl, matches on "/", does it's thing and then passes its output to json:generate()?
This stylesheet:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:json="http://json.org/">
<xsl:import href="xml-to-json.xsl"/>
<xsl:template match="/">
<xsl:variable name="vFirstPass">
<xsl:apply-templates/>
</xsl:variable>
<xsl:value-of select="json:generate($vFirstPass)"/>
</xsl:template>
<xsl:template match="node()|#*">
<xsl:copy>
<xsl:apply-templates select="node()|#*"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>

XLSX- how to get rid of the default namespace prefix x:?

I'm generating XLSX spreadsheet using OOXML SDK, and I need to get rid of x: namespace prefix. How can I achieve this?
using (SpreadsheetDocument doc = SpreadsheetDocument.Open("template.xlsx", true))
{
//Save the shared string table part
if (doc.WorkbookPart.GetPartsOfType().Count() > 0)
{
SharedStringTablePart shareStringPart = doc.WorkbookPart.GetPartsOfType().First();
shareStringPart.SharedStringTable.Save();
}
//Save the workbook
doc.WorkbookPart.Workbook.Save();
}
Here, the original XLSX file is coming from Excel 2007 and doesn't have the prefix, however, after the save operation the prefix appears. How can I avoid that?
Here is a modified version of the stylesheet linked by divo that strips only a single namespace and copies the rest verbatim:
<xsl:stylesheet version="1.0" xmlns:x="namespace-to-strip"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="no" encoding="UTF-8"/>
<xsl:template match="/|comment()|processing-instruction()">
<xsl:copy>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<xsl:template match="x:*">
<xsl:element name="{local-name()}">
<xsl:apply-templates select="#*|node()"/>
</xsl:element>
</xsl:template>
<xsl:template match="#x:*">
<xsl:attribute name="{local-name()}">
<xsl:value-of select="."/>
</xsl:attribute>
</xsl:template>
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Unless I'm much mistaken the original file is namespaced as well - only in the form of a default namespace. What's wrong with the namespace in the first place?