How to transform multiple files with in sub-directories using XSLT? - xslt

For example, there are chapter1 and chapter2 sub-folders inside parent folder, named:"S9ml". In both sub-directories:Chapter1 and Chapter2 has many .htmls. I want to transform all these .html' to remove white-spacing or Strip-white spacing. How do I do it? Please do help on how to run using Oxygen Editor?
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" indent="no" />
<xsl:template match="*">
<xsl:copy>
<xsl:copy-of select="#*" />
<xsl:apply-templates />
</xsl:copy>
</xsl:template>
<xsl:template match="comment()|processing-instruction()">
<xsl:copy />
</xsl:template>
</xsl:stylesheet>
I tried this but in config transform, when I select the ${cfdu} getting, your access is denied.

Related

Require Help in XSLT coding

I am new to XSLT .Kindly help me with the below query :
My Source XML:
<?xml version="1.0" encoding="UTF-8"?>
<ns1:Header1 xmlns:ns1="urn:src:abc">
<Header2>
<Header3>
<field1>1.1.2017</field1>
<field2>12</field2>
<field3> </field3>
</Header3>
</Header2>
</ns1:Header1>
Target/Expected XML
<?xml version="1.0" encoding="UTF-8"?>
<ns2:Header1 xmlns:ns2="urn:tar:abc" xmlns:v1="def.v1">
<Header2>
<v1:Header3>
<field1>1.1.2017</field1>
<field2>12</field2>
<field3> </field3>
</v1:Header3>
</Header2>
</ns2:Header1>
And also i need to remove the space/blank between the tag filed3 ( Field3 value sometimes will be blank)
I am using the below code for Transformation
<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="*">
<ns2:Header1 xmlns:ns2="urn:tar:abc" xmlns:v1="def.v1">
<Header2>
<xsl:copy-of select="//Header3"/>
</Header2>
</ns2:Header1>
</xsl:template>
</xsl:stylesheet>
I am not able to achieve my Target XML. Kindly help
Many thanks in advance
Regards,
Pavi
Your current template matches * which will match any element, but really you only want it to match the root element.
Additionally, as you want to change Header3 from being in no namespace, to being in the "def.v1" namespace, you should be making use of xsl:apply-templates, not xsl:copy-of
<xsl:template match="/*">
<ns2:Header1 xmlns:ns2="urn:tar:abc" xmlns:v1="def.v1">
<xsl:apply-templates />
</ns2:Header1>
</xsl:template>
You would then need a template matching Header3 to change the namespace
<xsl:template match="Header3" xmlns:v1="def.v1">
<v1:Header3>
<xsl:apply-templates />
</v1:Header3>
</xsl:template>
You would then just need the identity template to copy all other nodes without changes.
Try this XSLT
<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" indent="yes" />
<xsl:template match="/*">
<ns2:Header1 xmlns:ns2="urn:tar:abc" xmlns:v1="def.v1">
<xsl:apply-templates />
</ns2:Header1>
</xsl:template>
<xsl:template match="Header3" xmlns:v1="def.v1">
<v1:Header3>
<xsl:apply-templates />
</v1:Header3>
</xsl:template>
<xsl:template match="#*|node()">
<xsl:copy copy-namespaces="no">
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
See it in action at http://xsltransform.net/jz1PuQb

XSLT Error - element not declared

I need to transform the following xml
<node1 xmlns:ns1="namespace1">
<node2 xmlns:ns2="namespace2">
<node3...>
<node4...>
</node2>
</node1>
To
<NewNode2 xmlns:ns2="namespace2">
<node3...>
<node4...>
</NewNode2>
I use this XSLT
<?xml version="1.0" encoding="utf-16" ?>
<xsl:stylesheet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns:ns1="namespace1"
xmlns:ns2="namespace2">
<xsl:output omit-xml-declaration="yes" method="xml" version="1.0" />
<xsl:template match="/">
<xsl:apply-templates select="/" />
</xsl:template>
<xsl:template match="/" >
<NewNode2>
<xsl:copy-of select="//*[local-name()='node2']" />
</NewNode2 >
</xsl:template>
</xsl:stylesheet>
But this throws error in visual studio -
input validation error - element 'namespace1:node1' not declared
and element 'namespace2:node2' not declared
Your goal van be achieved with the following XSLT:
<?xml version="1.0" encoding="UTF-16"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ns1="namespace1"
xmlns:ns2="namespace2"
xmlns="namespace2">
<xsl:output omit-xml-declaration="yes" method="xml" version="1.0" />
<xsl:template match="/">
<xsl:apply-templates />
</xsl:template>
<xsl:template match="#*|*">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="ns1:node1">
<xsl:apply-templates />
</xsl:template>
<xsl:template match="ns2:node2">
<ns2:NewNode2>
<xsl:apply-templates />
</ns2:NewNode2>
</xsl:template>
</xsl:stylesheet>
The statement <xsl-templates select="/" /> inside <xsl:stylesheet match="/"> causes an infinite loop, since the matching template for the called 'root' is the template itself, which is calling the root.
The template <xsl template match="#*|*> belongs in almost all stylesheets, because this copies the content of all elements which are not otherwise specified (most applicable selection rule).
The other two templates specify specific behaviour for ns1:node1 (do not output any information at this level, but continue the template matching process for all further levels) and for ns2:node2 (create ns2:NewNode2 and continue to include all other availble information inside).

Add additional namespace with XSLT

I need to add an additional namespace to an already namespaced XML file but only if a particular element does not exist.
My XML doc looks like:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<everyone xmlns="AAA" xmlns:ns2="BBB" xmlns:ns3="CCC" company="TestingCorp">
<common>Stuff Here</common>
<ns2:person id="123">
<ns3:firstname>Billy</ns3:firstname>
<ns2:lastname>Bobby</ns2:lastname>
</ns2:person>
</everyone>
... and if there is no ns3:firstname element in the person element, I'd like to add a new namespace and (e.g. xmlns:frog="FFF") and also an additional element within person as shown below:
Desired Output:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<everyone xmlns="AAA" xmlns:ns2="BBB" xmlns:ns3="CCC" xmlns:frog="FFF" company="TestingCorp">
<common>Stuff Here</common>
<ns2:person id="123">
<frog:title>
<Master/>
</frog:title>
<ns2:lastname>Bobby</ns2:lastname>
</ns2:person>
</everyone>
My XSL doc currently is:
<?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" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<!-- Copy Everything -->
<xsl:template match="node()|#*">
<xsl:copy>
<xsl:apply-templates select="node()|#*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/*">
<xsl:element name="ns:{local-name()}">
<xsl:attribute name="frog">fff</xsl:attribute>
<xsl:apply-templates select="node()|#*" />
</xsl:element>
</xsl:template>
</xsl:stylesheet>
.... unfortunately this does not work.
I've tried lots of different things but can't seem to achieve this using XSLT v1.0. Any help would be greatly appreciated.
First you need to declare the various namespaces in your stylesheet, as well as the "AAA" default namespace
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="AAA"
xmlns:frog="FFF"
xmlns:ns2="BBB"
xmlns:ns3="CCC">
<xsl:output method="xml" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<!-- Copy Everything -->
<xsl:template match="node()|#*">
<xsl:copy>
<xsl:apply-templates select="node()|#*"/>
</xsl:copy>
</xsl:template>
<!-- for a Person with no firstname, add a frog:title -->
<xsl:template match="ns2:person[not(ns3:firstname)]">
<xsl:copy>
<!-- must handle attributes before elements/text nodes -->
<xsl:apply-templates select="#*" />
<frog:title>
<Master/>
</frog:title>
<xsl:apply-templates select="node()" />
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
This will produce
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<everyone xmlns="AAA" xmlns:ns2="BBB" xmlns:ns3="CCC" company="TestingCorp">
<common>Stuff Here</common>
<ns2:person id="123">
<frog:title xmlns:frog="FFF">
<Master/>
</frog:title>
<ns2:lastname>Bobby</ns2:lastname>
</ns2:person>
</everyone>
If the xmlns:frog absolutely must be on the everyone element rather than on each frog:title then you could add another template
<xsl:template match="/*">
<xsl:copy>
<xsl:copy-of select="document('')/xsl:stylesheet/namespace::frog" />
<xsl:apply-templates select="#*|node()" />
</xsl:copy>
</xsl:template>
to copy the namespace declaration off the stylesheet element (though this would mean that every output document has an xmlns:frog declaration even if it doesn't involve any frog:* elements).
Edit: apparently Xalan doesn't like the copy-of namespaces from document(''), as an alternative, if you know that the document element will always have the same name then you can hard code that as a literal result element
<xsl:template match="/*">
<everyone xmlns:frog="FFF">
<xsl:copy-of select="namespace::*" />
<xsl:apply-templates select="#*|node()" />
</everyone>
</xsl:template>
(technically it will do what you want even without the explicit xmlns:frog in this template, since literal result elements always get the namespace declarations that are in scope at the point in the stylesheet where they are declared, but the intention is arguably clearer if you include it)
This mailing list post gives some possible insights into the reason for document('') not working as it should.

how to remove a part of attribut to a node in xml file using xslt

I have the following xml code:
<OML>
<bg-def xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="EX1"/>
</OML>
I want to remove the attribute xmlns:xsi and its value using XSLT, so that the result will look like this:
<OML>
<bg-def name="EX1"/>
</OML>
I tryied to do this with the following XSLT code:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
xmlns:ex="http://exslt.org/dates-and-times" extension-element-prefixes="ex">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="no" xml:space="preserve"/>
<xsl:template match="node()|#*">
<xsl:copy>
<xsl:apply-templates select="node()|#*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="bg-def|# xmlns:xsi"/>
</xsl:transform>
Before I finished to write my code, my editor warned me that:
"W Namespace prefix xmlns has not been declared".
When I remove the expression :xsi and just write xmlns, there is no warning more. But when I compile and execute my program, nothing happens and I don't get the expected output.
I try also to change the last line of my xslt file with this:
<xsl:template match="bg-def|# name"/>
then the result is looking like this:
<OML>
<bg-def xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/>
</OML>
That means, the attribute name has been removed very well. But I want to do this with the attribute xmlns:xsi.
Can someone help me to do this please?
Thanks for any help.
Franky
Use following template for bd-def node:
<xsl:template match="bg-def">
<xsl:element name="{local-name()}">
<xsl:apply-templates select="node()|#*"/>
</xsl:element>
</xsl:template>
Instead of
<xsl:template match="bg-def|# name"/>
This template will create node bg-def and copy all it context nodes and attributes, but not namespaces
Check similar question:
remove namespace for a perticular element
Update:
Source file:
<OML>
<bg-def xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="EX1"/>
</OML>
Stylesheet:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
xmlns:ex="http://exslt.org/dates-and-times" extension-element-prefixes="ex">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="no" xml:space="preserve"/>
<xsl:template match="node()|#*">
<xsl:copy>
<xsl:apply-templates select="node()|#*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="bg-def">
<xsl:element name="{local-name()}">
<xsl:apply-templates select="node()|#*"/>
</xsl:element>
</xsl:template>
</xsl:transform>
Transformation result (Saxon 6.5.5 - Xslt 1.0):
<?xml version="1.0" encoding="UTF-8"?><OML>
<bg-def name="EX1"/>
</OML>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml"/>
<xsl:template match="*">
<xsl:element name="{local-name()}">
<xsl:apply-templates select="#*"/>
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
<xsl:template match="#*">
<xsl:attribute name="{local-name()}">
<xsl:value-of select="."/>
</xsl:attribute>
</xsl:template>
</xsl:stylesheet>

XSLT: Adding a node!

How do I encapsulate nodes around my XML blocks using XSLT?
For example, I have the following XML file.
<?xml version="1.0" encoding="iso-8859-1"?>
<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" omit-xml-declaration="yes" />
<xsl:template match="/">
<Root>
<VOBaseCollection>
<xsl:apply-templates select="Root/Location" />
</VOBaseCollection>
</Root>
</xsl:template>
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()" />
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
My input XML file looks like this.
<Root>
<Location><Name>Pennsylvania</Name><Type>State</Type></Location>
</Root>
I wish the output to look like this.
<Root><Container>
<Location><Name>Pennsylvania</Name><Type>State</Type></Location>
</Container>
</Root>
I wish to make sure that a node called <CONTAINER> gets applied every time, it copies over information from Root/Location. What changes do I need to do to my XSLT file?
Summarizing all the answers in comments, this:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="#*|node()" name="identity">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Location">
<Container>
<xsl:call-template name="identity"/>
</Container>
</xsl:template>
</xsl:stylesheet>
Result:
<Root>
<Container>
<Location>
<Name>Pennsylvania</Name>
<Type>State</Type>
</Location>
</Container>
</Root>
I am just guessing, and in guess mode it seems that you want this:
EDIT: helped by another guess by Mads Hansen...
Add this to the identity template you already have:
<xsl:template match="Location">
<CONTAINER><xsl:apply-templates/></CONTAINER>
</xsl:template>