Replace & with & in XML string in azure apim - replace

I have an xml string which I am setting as body and transforming that xml into required ones.
XML String:
XML_STRING= "<A><B>abc</B><C>abc&ade</C></A>";
When
<set-body>#((String)context.Variables["XML_STRING"])</set-body>
<xsl-transform>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes" />
<xsl:template match="/">
<xsl:copy-of select="A" />
</xsl:template>
</xsl:stylesheet>
</xsl-transform>
I am getting the below error:
xsl-transform (0.398 ms)
{
"messages": [
null,
"Invalid Xml passed to transform: ' ' is an unexpected token. The expected token is ';'. Line 1, position 2612.",
"' ' is an unexpected token. The expected token is ';'. Line 1, position 2612."
]
}
When I am changing "&" from xml_string to & it works fine. But I want to know that how we can replace it using code.

Related

Assign result of string containing special characters using encode-for-uri to variable

I query Microsoft Dynamics using fetchXML. They query is contstructed dynamically, by using an XML like syntax.
Simplified Example :
<fetch version="1.0" mapping="logical" page="1" count="5" returntotalrecordcount="true"><entity name="msdyn_bookingjournal"><attribute name="msdyn_name"/><attribute name="msdyn_starttime"/><attribute name="msdyn_endtime"/></entity></fetch>
The result is assigned to url parameter fetchXml and needs to be URL encoded.
fetchXML=%3Cfetch%20version%3D%221.0%22%20mapping%3D%22logical%22%20page%3D%221%22%20count%3D%225%22%20returntotalrecordcount%3D%22true%22%3E%3Centity%20name%3D%22msdyn_bookingjournal%22%3E%3Cattribute%20name%3D%22msdyn_name%22%2F%3E%3Cattribute%20name%3D%22msdyn_starttime%22%2F%3E%3Cattribute%20name%3D%22msdyn_endtime%22%2F%3E%3C%2Fentity%3E%3C%2Ffetch%3E
I wish to do the URL encoding in XSLT using encode-for-uri, however the XML like structure is giving parsing errors when saving in Notepad++ : 'XML Parsing error at Line 15: Extra content at the end of the document' or xsltfiddle "xsl:value-of" must not contain the '<' character.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:hci="http://sap.com/it/"
exclude-result-prefixes="hci"
version="2.0">
<xsl:output method="xml" indent="yes" encoding="utf-8" />
<!-- https://enlightenedintegration.wordpress.com/2018/02/27/cpi-updating-message-headers-and-property-through-xslt/ -->
<!-- needed to call the functions for setting header and propert values -->
<xsl:param name="exchange"/>
<xsl:param name="MSDQuery"/>
<xsl:param name="MSDHost" />
<xsl:param name="query"/>
<xsl:variable name ="encodedQuery"><xsl:value-of select="encode-for-uri('<fetch version=1.0 mapping=logical page=1 count=10>' + $query + '</fetch>')"/></xsl:variable>
<xsl:template match="/">
<xsl:value-of select="hci:setProperty($exchange, 'MSDQuery', $encodedQuery)" />
</xsl:template>
</xsl:stylesheet>
How can this query be encoded by encode-for-uri?
I created a fiddle : https://xsltfiddle.liberty-development.net/ncntCRX
Note :
The param values are assigned at runtime on the fly
I already left
out the double quotes in the query, example version="1.0" when
calling the function
The error message is clear. This is not well-formed XML:
<xsl:value-of select="encode-for-uri('<fetch version=1.0 mapping=logical page=1 count=10>' + $query + '</fetch>')"/>
Using entities, this is well-formed XML:
<xsl:value-of select="encode-for-uri('<fetch version=1.0 mapping=logical page=1 count=10>' + $query + '</fetch>')"/>
Note: $query should be a string, and it doesn't have to be "XML escaped" unless it's defined in an XML context.

XSLT: convert an URI parameter name and value

I am trying to convert the following URI parameters and respective values, using substring function. but it is giving error, obvious because it is not a string.
FROM: http://host/URI/api/abc/xml?xxx=a-b-c&pqr=123
TO: http://host/URI/api/abc/xml?yyy=d-e-f&pqr=123
Input is from a variable.
XSLT:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:dp="http://www.datapower.com/extensions" xmlns:func="http://exslt.org/functions" xmlns:str="http://exslt.org/strings" xmlns:dpfunc="http://www.datapower.com/extensions/functions" xmlns:dpconfig="http://www.datapower.com/param/config" xmlns:regexp="http://exslt.org/regular-expressions" extension-element-prefixes="dp func dpfunc dpconfig regexp" exclude-result-prefixes="dp func dpfunc dpconfig regexp">
<xsl:template match="/">
<xsl:variable name="currentURI" select="dp:variable('var://service/URI')"/>
<xsl:variable name="new-uri" select="regexp:replace($currentURI, 'xxx', 'yyy')"/>
<xsl:variable name="SubStringBeforeyyy" select="substring-before($new-uri, 'yyy=')"/>
<xsl:variable name="SubStringAfteryyy" select="substring-after($new-uri, '&' )"/> <!-- ERROR: -->
<xsl:variable name="NewParmValue" select="'d-e-f'"/>
<xsl:variable name="NewURI" select="concat($SubStringBeforeyyy, $NewParmValue, $SubStringAfteryyy)"/>
</xsl:template>
</xsl:stylesheet>
Error from xmlSpy is:
XML Production Error: Character ''' within text ''' does not fulfill production 'Name'.
XSLT is XML, so to write an ampersand(&) character you need to use
<xsl:variable name="SubStringAfteryyy" select="substring-after($new-uri, '&' )" />

To format all the Decimal Nodes to European Amount formatting

I have an XML which has Decimal field which need to formatted to European Currency format.
The Current its having US format.
-<Envelope>
-<Body>
-<getPriceRecommendationResponse>
-<status>
<statusCode>Success</statusCode>
</status>
-<priceRecommendation>
<tssArticleNumber>Item Number1234</tssArticleNumber>
<compoundCode>N123</compoundCode>
<compoundGroupCodeBucket>A</compoundGroupCodeBucket>
<compoundCodeBucket>N123 & others</compoundCodeBucket>
<qualityIndexCode>-</qualityIndexCode>
<qualityIndexBucket>Std Quality</qualityIndexBucket>
<weight>66.0341</weight>
<weightGroupBucket>BT 123.1234 and 12345.1234</weightGroupBucket>
<weightIsValidBucket>YES</weightIsValidBucket>
<subGroupCode>PT</subGroupCode>
<subGroupCodeBucket>7:B03</subGroupCodeBucket>
<stockDistinction>MTS</stockDistinction>
<productIdBucket>PT0401450-T46N</productIdBucket>
<referencePrice>42.076</referencePrice>
<averageQuantity>9</averageQuantity>
<quantityAdjustments>0.96</quantityAdjustments>
<highDV>2.123789</highDV>
<averageDV>1.25141</averageDV>
<lowDV>0.79983</lowDV>
<additionalAdjustmentsTotal>1</additionalAdjustmentsTotal>
<highPrice>19876.9124796544</highPrice>
<averagePrice>12345.5481540736</averagePrice>
<lowPrice>123344567.3075011968</lowPrice>
</priceRecommendation>
</getPriceRecommendationResponse>
</Body>
</Envelope>
Please help me with an xslt which can format all the Decimal Nodes in the XML.
The below is an xslt i am already using. I am expecting a similar one. Thanks
//this has been taken from a Microsoft knowledgebase aricle and strips out the
//namespaces from an XML message using a style sheet
XslTransform := XslTransform.XslTransform;
XMLStyleSheet := XMLStyleSheet.XmlDocument;
XMLStyleSheet.InnerXml(
'<?xml version="1.0" encoding="UTF-8"?>'+
'<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:msxml="urn:schemas-microsoft-com:xslt">'+
'<xsl:output method="xml" omit-xml-declaration="yes" version="1.0" encoding="UTF-8" indent="yes"/>' +
'<xsl:template match="#*|node()">'+
'<xsl:copy>'+
'<xsl:apply-templates select="#*|node()"/>'+
'</xsl:copy>'+
'</xsl:template>'+
'<xsl:template match="'+OldNode+'">'+
'<xsl:variable name="oldNode" select="'+OldNode+'"/>' +
'<xsl:variable name="newNodeXml">' +
'<xsl:element name="'+NewNode+'">' +
'<xsl:copy-of select="$oldNode/#*|node()"/>' +
'<xsl:copy-of select="$oldNode/child::*"/>' +
'<xsl:copy-of select="$oldNode/#*"/>' +
'</xsl:element>' +
'</xsl:variable>' +
'<xsl:copy-of select="msxml:node-set($newNodeXml)"/>' +
'</xsl:template>' +
'</xsl:stylesheet>'
);
XslTransform.Load(XMLStyleSheet);
writer := writer.StringWriter();
XslTransform.Transform(Source, nullXsltArgumentList, writer);
Destination := Destination.XmlDocument;
Destination.InnerXml(writer.ToString());
Thank you guys for your response. I hope i can make the things more clear to you. The European format is "," for Decimal separator and "." for Digit Grouping. Whereas US have the reverse. For example 1,000.156 in US and 1.000,156 for Europe. Yes Rnet i have tried the decimal-format its working fine, but the problem here is i need to use it multiple times for the Fields. I want an XSLT which change the format for all the decimal fields at once. I hope you got my point
Thank you Michael, I have tried your code but getting an error.
A call to System.Xml.Xsl.XslTransform.Load failed with this message: Expression must evaluate to a node-set.
I have changed the code little bit given by Michael, but still getting the same error.
'<?xml-stylesheet type="text/xsl" href="decimalformat.xsl"?>'+
'<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:strip-space elements="*"/>'+
'<xsl:decimal-format name="eu" decimal-separator="," grouping-separator="." />'+
'<!-- identity transform -->'+
'<xsl:template match="#*|node()">'+
' <xsl:copy>'+
' <xsl:apply-templates select="#*|node()"/>'+
' </xsl:copy>'+
'</xsl:template>'+
'<xsl:template match="*[number()=number()]">'+
' <xsl:copy>'+
' <xsl:value-of select=translate("format-number(., '#.##0,##########', 'eu'), ',', '.')" />'+
' </xsl:copy>'+
'</xsl:template>'+
'</xsl:stylesheet>'
In my application its not working. I have found a similar post here http://mikeschinkel.com/blog/gettingpastthexslterrorexpressionmustevaluatetoanodeset/#comment-484235
<xsl:value-of select="format-number(., '#.##0,##########', 'eu')" />
I am getting the error if i include the above code. i have tried it this way as well.
<xsl:value-of select=translate("format-number(., '#.##0,##########', 'eu'), ',', '.')" />
the problem here is i need to use it multiple times for the Fields. I
want an XSLT which change the format for all the decimal fields at
once.
This could be accomplished by a template that matches only elements containing strictly numeric values, for example:
XSLT 1.0
<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:strip-space elements="*"/>
<xsl:decimal-format name="eu" decimal-separator=',' grouping-separator='.' />
<!-- identity transform -->
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[number()=number()]">
<xsl:copy>
<xsl:value-of select="format-number(., '#.##0,##########', 'eu')" />
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Note:
This will not work with your input, because it contains an unescaped ampersand character;
This will not process elements that contain numbers as part of a string, e.g:
<weightGroupBucket>BT 123.1234 and 12345.1234</weightGroupBucket>
This has nothing to do with currency.

Boolean operator OR in where clause using XSLT

Hello folks,
I am trying to set a fixed value to a tag in XML on comparing to a value in condition. such as
<xsl:when test="(//TestInput='XYZA') OR (//TestInput='XYZB') OR (//TestInput='XYZC') OR (//TestInput='XYZD')">abcd</xsl:when>
when i trying to run the transformation with an XML with tag <TestInput>, it is giving me an error as
Extra illegal tokens: '(', '/', '/', 'TestInput', '=', ''XYZA'', ')', 'OR', '(', '/', '/', 'TestInput', '=', ''XYZB'', ')', 'OR', '(', '/', '/', 'TestInput', '=', ''XYZC'', ')', 'OR', '(', '/', '/', 'TestInput', '=', ''XYZD'', ')'
Please help me out in setting the value to this tag based on condition using OR operator in where clause.
Thanks in Advance
Case matters with XML/XSLT/XPath so use or instead of OR.
I created a test with the following XML:
<?xml version="1.0" encoding="utf-8"?>
<Test>
<Item>DAC</Item>
<Item>DAD</Item>
<Item>DAE</Item>
</Test>
And the following XSLT:
<?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:output method="xml" indent="yes"/>
<xsl:template match="#* | node()">
<test>
<xsl:choose>
<xsl:when test="//Item[text()='DAC'] or //Item[text()='DAE']">
<output>Here is the text!</output>
</xsl:when>
<xsl:otherwise></xsl:otherwise>
</xsl:choose>
</test>
</xsl:template>
</xsl:stylesheet>
I get the following output:
<?xml version="1.0" encoding="utf-8"?>
<test>
<output>Here is the text!</output>
</test>
Tested with Micorosft.Net's XmlDocument class. The critical difference is the case of the 'or' statement.
The problem is that //TestInput selects a set of elements instead of just one.
You should use xsl:for-each
<xsl:for-each select="//TestInput[.='a'or'b'or'c']">abc</xsl:for-each>

Getting substring based on particular index in xsl/xslt

I have a long web url in my xsl variable.
eg.
#url = "http://stackoverflow.com/questions/ask/2434/35454"
I need a substring from this based on 3rd index of "/". i.e I want to display only
http://stackoverflow.com
There is a substring(string, start, length) function in xsl but how do i find the length portion. I could not find any indexof function.
<xsl:value-of select="substring(url,1,length)"/>
My url is suppose - "http://stackoverflow.com/questions/ask/2434/35454"
Output I want is http://stackoverflow.com
Please suggest some solutions.
Use:
concat(substring-before(.,'//'),
'//',
substring-before(substring-after(., '//'),
'/'
)
)
Complete code example:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/*">
<xsl:value-of select=
"concat(substring-before(.,'//'),
'//',
substring-before(substring-after(., '//'),
'/'
)
)
"/>
</xsl:template>
</xsl:stylesheet>
when this transformation is applied on this XML document:
<t>http://stackoverflow.com/questions/ask/2434/35454</t>
the wanted, correct result is produced:
http://stackoverflow.com