How can I format the below XML date element in XSLT version1.0 ? The GenerationTime has to be formatted in pattern yyyy-MM-dd'T'HH:mm:ss in the output XML with the date value in UTC.
xslt processer used is xalan
<Values>
<value name="cardGenerated">yes</value>
<value name="GenerationTime">Tue Dec 29 14:32:53 EST 2020</value>
<Values>
the output would look like
<Values>
<value name="cardGenerated">yes</value>
<value name="GenerationTime">2020-12-19T19:32:53Z</value>
<Values>
Related
Question is how do i get my desired output?
I successfully created a group for each <LogistiekeDeelEenheid>
however, the <DeeleenheidAantal> field must also be filled with one value. For <LogistiekeDeelEenheid> 000094 <DeeleenheidAantal> has to be filled with 10 from <Value AttributeID = "att_NumberInCombiProduct"> 10 </Value> in the xsl to transform. And <LogistiekeDeelEenheid> 000072 <DeeleenheidAantal> has to be filled with 20 from <Value AttributeID = "att_NumberInCombiProduct"> 20 </Value> And <LogistiekeDeelEenheid> 000032 <DeeleenheidAantal> has to be filled with 35 from <Value AttributeID = "att_NumberInCombiProduct"> 35 </Value>
The xml to transform:
<Test>
<Product ID="LV-10432200" UserTypeID="CombiLogistiekeVariant">
<Name>1 - TEST1</Name>
<ProductCrossReference ProductID="Product-10430948"
Type="rpp_CombiLogistiekeVariant2Product">
<KeyValue KeyID="key_ProductGTIN">2311111</KeyValue>
<KeyValue KeyID="key_Productnummer">000094</KeyValue>
<MetaData>
<Value AttributeID="att_AantalInCombiProduct">10</Value>
</MetaData>
</ProductCrossReference>
<ProductCrossReference ProductID="Product-10431710"
Type="rpp_CombiLogistiekeVariant2Product">
<KeyValue KeyID="key_ProductGTIN">5449000018885</KeyValue>
<KeyValue KeyID="key_Productnummer">000072</KeyValue>
<MetaData>
<Value AttributeID="att_AantalInCombiProduct">20</Value>
</MetaData>
</ProductCrossReference>
<ProductCrossReference ProductID="Product-10431738"
Type="rpp_CombiLogistiekeVariant2Product">
<KeyValue KeyID="key_ProductGTIN">54419780</KeyValue>
<KeyValue KeyID="key_Productnummer">000032</KeyValue>
<MetaData>
<Value AttributeID="att_AantalInCombiProduct" Changed="true">35
</Value>
</MetaData>
</ProductCrossReference>
<Values>
<Value AttributeID="att_Productnummer">000001</Value>
<Value AttributeID="att_LVStatus" ID="2">Inactief</Value>
<Value AttributeID="att_LVOmschrijving">TEST Config 1</Value>
<Value AttributeID="att_LVNummer">1</Value>
</Values>
<Product ID="Pack-10432212" UserTypeID="Kleinverpakking">
<Name>21 - Kleinverpakking</Name>
<ProductCrossReference ProductID="LV-10432200"
Type="rpp_Verpakking-Kleinverpakking2Kleiner">
<MetaData>
<Value AttributeID="att_AantalInVerpakking">1</Value>
</MetaData>
</ProductCrossReference>
<Values>
<Value AttributeID="att_VerpakkingBreedte" UnitID="unece.unit.CMT">1</Value>
<Value AttributeID="att_VerpakkingGewichtBruto" UnitID="181">1
</Value>
<Value AttributeID="att_LVNummer">1</Value>
<Value AttributeID="att_VerpakkingHoogte" UnitID="unece.unit.CMT">1</Value>
<Value AttributeID="att_Productnummer">000001</Value>
<Value AttributeID="att_VerpakkingDiepte" UnitID="unece.unit.CMT">1</Value>
<Value AttributeID="att_PrimaireGTIN" Derived="true">Primaire GTIN
Ontbreekt
</Value>
</Values>
</Product>
</Product>
</Test>
And must be transformed to:
<LogistiekeDeelEenheid>
<DeeleenheidArtikelNummer>000094</DeeleenheidArtikelNummer>
<DeeleenheidLogistiekeVariant>0</DeeleenheidLogistiekeVariant>
<DeeleenheidCode>1</DeeleenheidCode>
<DeeleenheidLinkType>4</DeeleenheidLinkType>
<DeeleenheidAantal>10</DeeleenheidAantal>
</LogistiekeDeelEenheid>
<LogistiekeDeelEenheid>
<DeeleenheidArtikelNummer>000072</DeeleenheidArtikelNummer>
<DeeleenheidLogistiekeVariant>0</DeeleenheidLogistiekeVariant>
<DeeleenheidCode>1</DeeleenheidCode>
<DeeleenheidLinkType>4</DeeleenheidLinkType>
<DeeleenheidAantal>20</DeeleenheidAantal>
</LogistiekeDeelEenheid>
<LogistiekeDeelEenheid>
<DeeleenheidArtikelNummer>000032</DeeleenheidArtikelNummer>
<DeeleenheidLogistiekeVariant>0</DeeleenheidLogistiekeVariant>
<DeeleenheidCode>1</DeeleenheidCode>
<DeeleenheidLinkType>4</DeeleenheidLinkType>
<DeeleenheidAantal>35</DeeleenheidAantal>
</LogistiekeDeelEenheid>
My xslt:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output encoding="UTF-8" indent="yes" method="xml"/>
<xsl:template match="/">
<xsl:apply-templates select="Test/Product"/>
</xsl:template>
<xsl:template match="Test/Product">
<xsl:for-each-group select="//ProductCrossReference[#Type='rpp_CombiLogistiekeVariant2Product']" group-by="//ProductCrossReference/KeyValue[#KeyID='key_Productnummer']">
<xsl:variable select="current-grouping-key()" name="Productnummer"/>
<test>
<xsl:value-of select="../Name"/>
</test>
<LogistiekeDeelEenheid>
<DeeleenheidArtikelNummer>
<xsl:value-of select="$Productnummer"/>
</DeeleenheidArtikelNummer>
<DeeleenheidLogistiekeVariant>0</DeeleenheidLogistiekeVariant>
<DeeleenheidCode>1</DeeleenheidCode>
<DeeleenheidLinkType>4</DeeleenheidLinkType>
<DeeleenheidAantal>
<xsl:value-of select="../ProductCrossReference/MetaData/Value[#AttributeID='att_AantalInCombiProduct']"/>
</DeeleenheidAantal>
</LogistiekeDeelEenheid>
</xsl:for-each-group>
</xsl:template>
</xsl:stylesheet>
But if i use this code, i get this result what is incorrect. In the first should be 10 in the second 20 and in the third 35
<?xml encoding="UTF-8" version="1.0"?>
<test>1 - TEST1</test>
<LogistiekeDeelEenheid>
<DeeleenheidArtikelNummer>000094</DeeleenheidArtikelNummer>
<DeeleenheidLogistiekeVariant>0</DeeleenheidLogistiekeVariant>
<DeeleenheidCode>1</DeeleenheidCode>
<DeeleenheidLinkType>4</DeeleenheidLinkType>
<DeeleenheidAantal>10 20 35
</DeeleenheidAantal>
</LogistiekeDeelEenheid>
<test>1 - TEST1</test>
<LogistiekeDeelEenheid>
<DeeleenheidArtikelNummer>000072</DeeleenheidArtikelNummer>
<DeeleenheidLogistiekeVariant>0</DeeleenheidLogistiekeVariant>
<DeeleenheidCode>1</DeeleenheidCode>
<DeeleenheidLinkType>4</DeeleenheidLinkType>
<DeeleenheidAantal>10 20 35
</DeeleenheidAantal>
</LogistiekeDeelEenheid>
<test>1 - TEST1</test>
<LogistiekeDeelEenheid>
<DeeleenheidArtikelNummer>000032</DeeleenheidArtikelNummer>
<DeeleenheidLogistiekeVariant>0</DeeleenheidLogistiekeVariant>
<DeeleenheidCode>1</DeeleenheidCode>
<DeeleenheidLinkType>4</DeeleenheidLinkType>
<DeeleenheidAantal>10 20 35
</DeeleenheidAantal>
</LogistiekeDeelEenheid>
The suggestion I made in the comment, adjusted to the code you have posted later, would result in
<xsl:template match="Test/Product">
<xsl:for-each-group select="ProductCrossReference[#Type='rpp_CombiLogistiekeVariant2Product']"
group-by="KeyValue[#KeyID='key_Productnummer']">
<xsl:variable select="current-grouping-key()" name="Productnummer"/>
<test>
<xsl:value-of select="../Name"/>
</test>
<LogistiekeDeelEenheid>
<DeeleenheidArtikelNummer>
<xsl:value-of select="$Productnummer"/>
</DeeleenheidArtikelNummer>
<DeeleenheidLogistiekeVariant>0</DeeleenheidLogistiekeVariant>
<DeeleenheidCode>1</DeeleenheidCode>
<DeeleenheidLinkType>4</DeeleenheidLinkType>
<DeeleenheidAantal>
<xsl:value-of select="MetaData/Value[#AttributeID='att_AantalInCombiProduct']"/>
</DeeleenheidAantal>
</LogistiekeDeelEenheid>
</xsl:for-each-group>
</xsl:template>
At https://xsltfiddle.liberty-development.net/ei5R4tY I applied the suggestion to your edited input sample and the result has e.g. <DeeleenheidAantal>10</DeeleenheidAantal>, that is, single values for that item in the result.
I must admit that your sample data with the nesting is still not clear to me but feel free to further edit your question and clarify which data you want to process and group.
I have columns as VALUE in DUMMY table with type XMLTYPE.
It contains:
<?xml version="1.0"?>
<ROWSET>
<Value>
<Data>802
</Data>
</Value>
<Value>
<Data>902
</Data>
</Value>
</ROWSET>
I need to replace it with NULL for 802 value tag.
The output should be :
<?xml version="1.0"?>
<ROWSET>
<Value>
<Data>902
</Data>
</Value>
</ROWSET>
802 value tag should be removed with NULL.
I tried UpdateXML():
update Dummy set VALUE=updatexml(VALUE,'ROWSET/Value/Data/text()','');
But it will update only 802 value with null.
2nd Approach:
update Dummy set Value=updatexml(Value,'ROWSET','');
But it will delete everything inside ROWSET tag.Then,It will contain only :
<?xml version="1.0"?>
<ROWSET/>
I tried Replace() too.
update Dummy set emps=replace('
<Value><Data>802
</Data></Value>',null);
Then it will remove other values from VALUE column and remain only the mentioned tag in replace().
After this replace(), It contains :
<Value><Data>802
</Data></Value>
Please suggest me on this.
You need
deleteXml() instead of updateXml(), and
a correct XPath for what's to be deleted.
Let's test our XPath first
with input$ as (
select --+ no_merge
xmltype(q'{<?xml version="1.0"?>
<ROWSET>
<Value>
<Data>802
</Data>
</Value>
<Value>
<Data>902
</Data>
</Value>
</ROWSET>}') as xx
from dual
)
select
xmlserialize(document X.xx indent) as original,
xmlserialize(document
deletexml(X.xx, '/ROWSET/Value[normalize-space(Data)="802"]')
indent
) as with_802_removed
from input$ X;
... yields...
ORIGINAL WITH_802_REMOVED
---------------------- ----------------------
<?xml version="1.0"?> <?xml version="1.0"?>
<ROWSET> <ROWSET>
<Value> <Value>
<Data>802 <Data>902
</Data> </Data>
</Value> </Value>
<Value> </ROWSET>
<Data>902
</Data>
</Value>
</ROWSET>
Note: The xmlserialize() function is used here only for pretty-printing.
Now your update
update Dummy X
set X.value = deletexml(X.value, '/ROWSET/Value[normalize-space(Data)="802"]');
Note for Oracle 12c: There should be a more elegant solution to this using XQuery, but I was not able to get a full grasp on the XQuery language yet, hence I present you the deleteXml() solution only.
Is there way to fetch elements of previous iteration.
I have the following XML document (abbreviated for the better overview):
<requests>
<request>
<id>514</id>
<status>accepted</status>
<updated>"2013-10-07T12:00:51.508"</updated>
<query>
<![CDATA[Select column1 from table1]]>
</query>
</request>
<request>
<id>22</id>
<status>rejected</status>
<updated>"2012-11-07T12:00:51.508"</updated>
<query>
<![CDATA[Select column3 from table2]]>
</query>
</request>
<request>
<id>7523</id>
<status>accepted</status>
<updated>"2012-01-07T02:00:52.508"</updated>
<query>
<![CDATA[Select column8 from table3]]>
</query>
</request>
<request>
<id>84</id>
<status>accepted</status>
<updated>"2000-12-07T12:00:51.1"</updated>
<query>
<![CDATA[Select column1 from table1]]>
</query>
</request>
<request>
<id>999</id>
<status>accepted</status>
<updated>"2006-12-07T12:00:51.1"</updated>
<query>
<![CDATA[Select column1 from table1]]>
</query>
</request>
.
.
.
</requests>
Now I have to select all nodes with the status: "accepted" group them by the table and then by the column which is queried and for each column select only two requests with the most recent update time. The output should be ids of these node given as simple text. For example for the query 'Select column1 from table 1' 514 and 999 should be selected for output whereas 84 not. I have read about muenchian method but I could not apply it on the parsed text (in this case the text in query).
That is why I tried to figure out the way to obtain information from previous iteration so I can sort nodes by the given criteria and find id that I look for.
For example:
<xsl:for-each select="*[local-name()='requests']/*[local-name='request'][#status='accepted']" >
<xsl:sort select="string(*[local-name()='query']/text())" order="text" data-type="number" />
<xsl:sort select="#pdated" order="descending" data-type="number" />
<xsl:value-of select="string(preceding-sibling::*[1]/*[local-name()='query']/text()) />
Now this works but not the way I want it, it returns the preceding sibling in the document but not the query text of previous iteration. Is something like this possible?
Thanks
XSLT is a declarative language and while for-each might look like a procedural for loop there is no concept of that in the XSLT 1.0 or 2.0 specification. Therefore the concept of previous iteration does not exist either. Only XSLT 3.0 with the xsl:iterate provides something along those lines to allow processing of very large documents without loading the complete document tree into memory.
With XSLT 1.0 you will need to use a different approach, you would need to post the structure of the input samples you want to process and the corresponding result you want to create to allow us to help with concrete code.
I have read about muenchian method but I could not apply it on the
parsed text (in this case the text in query).
This is how you can apply Muenchian grouping based on parsed text - in this case, the column name:
<?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:strip-space elements="*"/>
<xsl:key name="req" match="request[status='accepted']" use="substring-before(substring-after(query ,'Select '), ' from')" />
<xsl:template match="/">
<root>
<xsl:for-each select="requests/request[status='accepted'][count(. | key('req', substring-before(substring-after(query ,'Select '), ' from'))[1]) = 1]">
<group>
<xsl:value-of select="query"/>
</group>
</xsl:for-each>
</root>
</xsl:template>
</xsl:stylesheet>
Applied to you example input, this will result in:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<group>Select column1 from table1</group>
<group>Select column8 from table3</group>
</root>
Now you just need to sort the group members by update time and output the first two.
Good Day,
I have an XSLT template I'm assembling that look like:
<xsl:for-each select="CarParts/Items">
<div class="columns"><xsl:value-of select="Quantity"/></div>
<div class="columns"><xsl:value-of select="Amount"/></div>
<div class="columns">[SUBTOTAL]</div><br />
</xsl:for-each>
I know that I can define an XSLT variable like this:
<xsl:variable name="totalAmount" select="sum(CarParts/Items/Amount)" />
But I want my XSLT variable to be [SUBTOTAL] which is equal to Quantity * Amount within the for-each select loop. Is this possible? If this was SQL, this would be the equivalent of a computed column.
Any suggestions?
TIA,
coson
What you want to do is cast the value to a number, then you can multiply it as desired:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="/">
<results>
<xsl:for-each select="CarParts/Items">
<Item id="{position()}">
<q><xsl:value-of select="Quantity"/></q>
<a><xsl:value-of select="Amount"/></a>
<st><xsl:value-of select="number(Quantity)*number(Amount)"/></st>
</Item>
</xsl:for-each>
</results>
</xsl:template>
</xsl:stylesheet>
I changed the formatting a little since there was no provided input/CSS, but you should see what I was going for. Running it on my sample input of
<CarParts>
<Items>
<Quantity>1</Quantity>
<Amount>100.00</Amount>
</Items>
<Items>
<Quantity>2</Quantity>
<Amount>25.00</Amount>
</Items>
<Items>
<Quantity>3</Quantity>
<Amount>6</Amount>
</Items>
</CarParts>
I get the result of
<?xml version="1.0" encoding="utf-8"?>
<results>
<Item id="1">
<q>1</q>
<a>100.00</a>
<st>100</st>
</Item>
<Item id="2">
<q>2</q>
<a>25.00</a>
<st>50</st>
</Item>
<Item id="3">
<q>3</q>
<a>6</a>
<st>18</st>
</Item>
</results>
I was given the following XML:
<root>
<items>
<item>
<title>Item</title>
<details>
<data xmlns="http://some_url">
<length>10</length>
<weight>1.2</weight>
</data>
</details>
</item>
</items>
</root>
Following XPath does not work meaning nothing is printed like the "data" element does not exists:
/root/items/item/details/data
But when I remove "xmlns" namespace attribute of "data" element it's content is printed.
How should the xpath expression look like to work without deleting "xmlns" namespace attribute of "data" element?
I'm using SAXON and XSL 1.0.
This is one of the most FAQ in XPath / XSLT:
XPath interprets an unprefixed element name as belonging to "no namespace" and this is the reason elements with unprefixed names belonging to a default (nonempty) namespace aren't selected when only their unprefixed name is specified as a node-test in an XPath expression.
The solution is either:
Create a namespace binding where a prefix (say "x") is associated with the default namespace, then specify x:elementName instead of elementName.
Use long, ugly and unreliable expressions like: *[name() = 'elementName']
Here is an XSLT transformation using the above method1. :
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:a="http://some_url">
<xsl:output method="text"/>
<xsl:template match="/">
<xsl:value-of select=
"/root/items/item/details/a:data/a:weight"/>
</xsl:template>
</xsl:stylesheet>
When this transformation is applied (using Saxon 6.5.4 or any other compliant XSLT 1.0 processor) on the provided XML document:
<root>
<items>
<item>
<title>Item</title>
<details>
<data xmlns="http://some_url">
<length>10</length>
<weight>1.2</weight>
</data>
</details>
</item>
</items>
</root>
The correct/wanted node is selected and its string value is copied to the output:
1.2
In XPath, you have to assign a prefix to the namespace. How you do that depends on the XPath software/library you are using, but assuming you associate the namespace URI http://some_url with the namespace prefix someUrl, you can change your XPath expression as follows:
/root/items/item/details/someUrl:data