I have an XML with some mixed Nodes,and I want to get just the value of the parent and not the child.
My XML
<?xml version="1.0" encoding="UTF-8"?>
<Records>
<DET>
<detnumber>100126</detnumber>
<EmployeeNo>100126</EmployeeNo>
<action>CHANGE</action>
<first_name> NewHire-4th
<previous>NewHire</previous>
</first_name>
<last_name>Test-Changed 4th
<previous>Test-Changed 3rd</previous>
</last_name>
<birth_name>
NewHire-Changed 4th
<previous>NewHire-Changed 3rd</previous>
</birth_name>
<formal_name>
NewHire-4th Test-Changed 4th
<previous>NewHire Test-Changed 3rd</previous>
</formal_name>
<salutation>
MISS
<previous>MRS</previous>
</salutation>
<email_address>
testHire4#gmail.com
<previous>testHire2#gmail.com</previous>
</email_address>
</DET>
</Records>
Using XSLT 2.0 ,
I am mostly using copy of in my xslt, But the whole Node and its child are being copied. I need to be able to restrict only to the parent.
<xsl:copy-of select="first_name"/>
<xsl:copy-of select="last_name"/>
<xsl:copy-of select="birth_name"/>
<xsl:copy-of select="formal_name"/>
<xsl:copy-of select="salutation"/>
Below is my preferred output
<?xml version="1.0" encoding="UTF-8"?>
<Records>
<DET>
<detnumber>100126</detnumber>
<EmployeeNo>100126</EmployeeNo>
<action>CHANGE</action>
<first_name> NewHire-4th</first_name>
<last_name>Test-Changed 4th</last_name>
<birth_name>NewHire-Changed 4th</birth_name>
<formal_name>NewHire-4th Test-Changed 4th</formal_name>
<salutation>MISS</salutation>
<email_address>testHire4#gmail.com</email_address>
</DET>
</Records>
Check this Code:-
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" indent="yes"/>
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="previous"/>
</xsl:stylesheet>
Related
I am trying remove blank lines without stripping spaces and indentation, because my requirement is indented XML. Can anyone help me, please?
Input XML
<?xml version="1.0" encoding="UTF-8"?>
<Export>
<bio id="b0001">
<p>Maciej</p>
</bio>
<funding-group>
<award-group>
<funding-source>
<named-content content-type="funder-name">Narodowe</named-content>
<named-content content-type="funderidentifier">501100004281</named-content>
</funding-source>
<award-id>/19/B/HS4/</award-id>
<award-id>3</award-id>
</award-group>
</funding-group>
</Export>
Expected Result
<?xml version="1.0" encoding="UTF-8"?>
<Export>
<bio id="b0001">
<p>Maciej</p>
</bio>
<funding-group>
<award-group>
<funding-source>
<named-content content-type="funder-name">Narodowe Centrum Nauki</named-content>
<named-content content-type="funderidentifier">10.13039/501100004281</named-content>
</funding-source>
<award-id>/19/B/HS4/</award-id>
<award-id>3</award-id>
</award-group>
</funding-group>
</Export>
XSLT I have tried this xsl but it's not worked properly if i have run this xsl then generate XML single line.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs"
version="2.0">
<xsl:output method="xml" omit-xml-declaration="no"/>
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="//text()">
<xsl:value-of select="translate(.,'
', '')"/>
</xsl:template>
</xsl:stylesheet>
I am attempting to write an XSLT stylesheet that removes the milliseconds from any timestamp in an XML form. My sample XML below is just a sample there could conceivably be any number of timestamps in the envelope. So I'm thinking I need to pattern match the timestamp and then transform it. I can use XSLT 2.0 The original message looks like:
<?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:Header xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
</soap:Header>
<soap:Body>
<Staging_Submit_Service xmlns="com.xxx">
<u_From_Partner__c>Our Partner</u_From_Partner__c>
<u_To_Partner__c>Us</u_To_Partner__c>
<u_Partner_CI__c/>
<u_Partner_ID__c>10051</u_Partner_ID__c>
<u_Partner_Name__c>ROSEVILLE</u_Partner_Name__c>
<u_Partner_Reported_Date__c>2016-07-26T17:38:28.746134Z</u_Partner_Reported_Date__c>
<u_Partner_Status_Reason__c>Failure in System</u_Partner_Status_Reason__c>
<u_Partner_Submit_Date__c>2016-07-25T18:11:23.5443Z</u_Partner_Submit_Date__c>
<u_Partner_Priority__c>Low</u_Partner_Priority__c>
<u_Partner_Service_Type>Event</u_Partner_Service_Type>
</Staging_Submit_Service>
</soap:Body>
</soap:Envelope>
and my resulting xml needs to look like:
<?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:Header xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
</soap:Header><soap:Body>
<Staging_Submit_Service xmlns="com.xxx">
<u_From_Partner__c>Our Partner</u_From_Partner__c>
<u_To_Partner__c>Us</u_To_Partner__c>
<u_Partner_CI__c/>
<u_Partner_ID__c>10051</u_Partner_ID__c>
<u_Partner_Name__c>ROSEVILLE</u_Partner_Name__c>
<u_Partner_Reported_Date__c>2016-07-26T17:38:28Z</u_Partner_Reported_Date__c>
<u_Partner_Status_Reason__c>Failure in System</u_Partner_Status_Reason__c>
<u_Partner_Submit_Date__c>2016-07-25T18:11:23Z</u_Partner_Submit_Date__c>
<u_Partner_Priority__c>Low</u_Partner_Priority__c>
<u_Partner_Service_Type>Event</u_Partner_Service_Type>
</Staging_Submit_Service>
</soap:Body>
</soap:Envelope>
Notice the timestamps. I started down this path but it doesn't seem to be getting me where I need to be.
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ns1="java:com.verizon.webservices.adapter.clecclient">
<xsl:output method="xml" indent="no" version="1.0" encoding="UTF-8" omit-xml-declaration="yes"/>
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()" />
</xsl:copy>
</xsl:template>
<xsl:template match="#*|node()"
<xsl:copy>
<xsl:value-of select="." />
<xsl:value-of select='matches(.,".*[0-9]\{4\}-[0-9]\{2\}.*:[0-9]\{2\}*")'/>
<xsl:value-of select='replace(., "s/.*[0-9]\{4\}-[0-9]\{2\}.*:[0-9]\{2\}\(\.[0-9]*\).*/\1","")'/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
I am really only vaguely familiar with XSLT and this particular problem requires me to use it.
From the comments it seems that you can only use an XSLT 1.0 solution.
Here is one:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:df="com.xxx">
<xsl:output omit-xml-declaration="yes"/>
<xsl:template match="node()|#*">
<xsl:copy>
<xsl:apply-templates select="node()|#*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="df:u_Partner_Reported_Date__c/text()
|df:u_Partner_Submit_Date__c/text()">
<xsl:value-of select="concat(substring-before(.,'.'), 'Z')"/>
</xsl:template>
</xsl:stylesheet>
When this transformation is applied on the provided XML document:
<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:Header xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
</soap:Header>
<soap:Body>
<Staging_Submit_Service xmlns="com.xxx">
<u_From_Partner__c>Our Partner</u_From_Partner__c>
<u_To_Partner__c>Us</u_To_Partner__c>
<u_Partner_CI__c/>
<u_Partner_ID__c>10051</u_Partner_ID__c>
<u_Partner_Name__c>ROSEVILLE</u_Partner_Name__c>
<u_Partner_Reported_Date__c>2016-07-26T17:38:28.746134Z</u_Partner_Reported_Date__c>
<u_Partner_Status_Reason__c>Failure in System</u_Partner_Status_Reason__c>
<u_Partner_Submit_Date__c>2016-07-25T18:11:23.5443Z</u_Partner_Submit_Date__c>
<u_Partner_Priority__c>Low</u_Partner_Priority__c>
<u_Partner_Service_Type>Event</u_Partner_Service_Type>
</Staging_Submit_Service>
</soap:Body>
</soap:Envelope>
the wanted, correct result is produced:
<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:Header>
</soap:Header>
<soap:Body>
<Staging_Submit_Service xmlns="com.xxx">
<u_From_Partner__c>Our Partner</u_From_Partner__c>
<u_To_Partner__c>Us</u_To_Partner__c>
<u_Partner_CI__c/>
<u_Partner_ID__c>10051</u_Partner_ID__c>
<u_Partner_Name__c>ROSEVILLE</u_Partner_Name__c>
<u_Partner_Reported_Date__c>2016-07-26T17:38:28Z</u_Partner_Reported_Date__c>
<u_Partner_Status_Reason__c>Failure in System</u_Partner_Status_Reason__c>
<u_Partner_Submit_Date__c>2016-07-25T18:11:23Z</u_Partner_Submit_Date__c>
<u_Partner_Priority__c>Low</u_Partner_Priority__c>
<u_Partner_Service_Type>Event</u_Partner_Service_Type>
</Staging_Submit_Service>
</soap:Body>
</soap:Envelope>
Try
<xsl:template match="*[not(*) and . castable as xs:dateTime]">
<xsl:copy>
<xsl:value-of select="format-dateTime(., '[Y0001]-[M01]-[D01]T[H01]:[m01]:[s01]')"/>
</xsl:copy>
</xsl:template>
plus your first template.
So the complete stylesheet is
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs" version="2.0">
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[not(*) and . castable as xs:dateTime]">
<xsl:copy>
<xsl:value-of select="format-dateTime(., '[Y0001]-[M01]-[D01]T[H01]:[m01]:[s01]')"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Actually the above seems to not preserve any timezone suffix present and ensuring it is output as Z if it is UTC is a bit tricky, but I think if you make the value-of
<xsl:value-of select="if (timezone-from-dateTime(.) eq xs:dayTimeDuration('PT0H')) then format-dateTime(., '[Y0001]-[M01]-[D01]T[H01]:[m01]:[s01]Z') else format-dateTime(., '[Y0001]-[M01]-[D01]T[H01]:[m01]:[s01][Z]')"/>
then it works fine.
It seems the problem about the timezone Z was resolved in https://www.w3.org/TR/xpath-functions-31/#rules-for-datetime-formatting to allow
<xsl:value-of select="format-dateTime(., '[Y0001]-[M01]-[D01]T[H01]:[m01]:[s01][Z00:00t]')"/>
but I have not tested whether that works with XmlPrime or processors other than Saxon.
The following works for me with Xalan inside Oxygen as far as identifying the two elements with dateTimes in your input sample and reformatting them to remove the decimals of the seconds:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:date="http://exslt.org/dates-and-times"
exclude-result-prefixes="xs date" version="1.0">
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[not(*) and string-length() > 19 and date:date() != '']">
<xsl:copy>
<xsl:value-of select="date:format-date(date:date(.), "yyyy-MM-dd'T'HH:mm:ssZ")"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
However the created output dates differ, the input <u_Partner_Reported_Date__c>2016-07-26T17:38:28.746134Z</u_Partner_Reported_Date__c> shows up as <u_Partner_Reported_Date__c>2016-07-25T22:00:00+0000</u_Partner_Reported_Date__c>, so either the date parsing or formatting is broken.
I am struggling a bit with a solution for the following problem and was hoping someone could point me in the right direction.
To illustrate the issue I will try and pair it down to its most simple form. I have the following data:
<?xml version="1.0" encoding="UTF-8"?>
<SampleData>
<Data>AA-BRAND1,BB-BRAND1,AA-BRAND2</Data>
</SampleData>
and need to produce the following output:
<?xml version="1.0" encoding="UTF-8"?>
<ListOfBrandSales>
<BrandSales>
<BrandChannel>AA</BrandChannel>
<ListOfBrand>
<Brand>BRAND1</Brand>
<Brand>BRAND2</Brand>
</ListOfBrand>
</BrandSales>
<BrandSales>
<BrandChannel>BB</BrandChannel>
<Brand>BRAND1</Brand>
</BrandSales>
</ListOfBrandSales>
I have been playing with the tokenize and distinct-values functions but am unable to get it. Seems like I need to nest these functions and not sure if it is possible. My apologies if the solution is obvious but I am a bit new to XSLT.
Thanks in advance.
How about:
XSLT 2.0
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:variable name="tokens" select="tokenize(/SampleData/Data, ',')" />
<xsl:variable name="channels">
<xsl:for-each select="$tokens">
<channel><xsl:value-of select="substring-before(., '-')"/></channel>
</xsl:for-each>
</xsl:variable>
<xsl:template match="/">
<ListOfBrandSales>
<xsl:for-each select="distinct-values($channels/channel)">
<BrandSales>
<BrandChannel><xsl:value-of select="."/></BrandChannel>
<ListOfBrand>
<xsl:for-each select="$tokens[starts-with(., current())]">
<Brand><xsl:value-of select="substring-after(., '-')"/></Brand>
</xsl:for-each>
</ListOfBrand>
</BrandSales>
</xsl:for-each>
</ListOfBrandSales>
</xsl:template>
</xsl:stylesheet>
Or, if you prefer:
XSLT 2.0
<xsl:stylesheet version="2.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="/">
<ListOfBrandSales>
<xsl:for-each-group select="tokenize(SampleData/Data, ',')" group-by="substring-before(., '-')">
<BrandSales>
<BrandChannel><xsl:value-of select="current-grouping-key()"/></BrandChannel>
<ListOfBrand>
<xsl:for-each select="current-group()">
<Brand><xsl:value-of select="substring-after(., '-')"/></Brand>
</xsl:for-each>
</ListOfBrand>
</BrandSales>
</xsl:for-each-group>
</ListOfBrandSales>
</xsl:template>
</xsl:stylesheet>
I'm calling in XML using document(). I need to transform the imported XML. Is this possible?
<xsl:copy-of select="document('C:\my.xml')/*"/>
<xsl:apply-templates/>
Thanks!
Use <xsl:apply-templates select="document('file:///c:/my.xml')/*"/>, then you only need to add templates for the nodes in the file.
For example, a my.xml is given below
<?xml version="1.0" standalone="no"?>
<root>
<a>XXX</a>
<b>YYY</b>
</root>
and the current xml is given below:
<?xml version="1.0" encoding="UTF-8"?>
<root_test>
<test1>123</test1>
<test2>456</test2>
</root_test>
when the following stylesheet is applied:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:template match="root_test">
<xsl:copy>
<xsl:apply-templates/>
<xsl:apply-templates select="document('my.xml')/*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="a[document('my.xml')]">
<success><xsl:apply-templates/></success>
</xsl:template>
</xsl:stylesheet>
it outputs
<?xml version="1.0" encoding="utf-8"?>
<root_test>
123
456
<success>XXX</success>
YYY
</root_test>
notice that the templates for node a in my.xml has been applied.
The XSLT below creates result-documents as desired, with one exception: the result document ends up in the directory where the stylesheet was invoked from. I want the result document to be where it was found (i.e. overwrite itself with the transform version).
How can I do that?
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="2.0" xpath-default-namespace="http://www.w3.org/1999/xhtml">
<xsl:template match="/">
<xsl:for-each select="collection(iri-to-uri('file:///home/paul/Text/?select=*.xhtml'))">
<xsl:variable name="filename">
<xsl:value-of select="tokenize(document-uri(.), '/')[last()]"/>
</xsl:variable>
<xsl:result-document indent="yes" method="xml" href="{$filename}">
<xsl:apply-templates/>
</xsl:result-document>
</xsl:for-each>
</xsl:template>
<xsl:template match="node()|#*">
<xsl:copy>
<xsl:apply-templates select="node()|#*"/>
</xsl:copy>
</xsl:template>
<!-- transform templates removed -->
</xsl:stylesheet>
Try just using href="{document-uri(.)}" to use the full uri as the target rather than doing the tokenize to pull out the last segment.