transform XML into one that can be imported into Access - xslt

I want to use XSLT to transform XML into one that can be imported into Access the input file is:
<?xml version="1.0" encoding="UTF-8"?>
<Document xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<DatosGen>
<Vendedor>
<Nombre>Juan Garcia Sanchez</Nombre>
<Codigo>VE144</Codigo>
</Vendedor>
<Fecha>30-abr-2015</Fecha>
</DatosGen>
<Pedidos>
<Pedido>
<Cabecera>
<Numero>34</Numero>
<Fecha>28-abr-2015</Fecha>
<Cliente>
<Nombre>Antonio Lopez Martin</Nombre>
<Codigo>CL121</Codigo>
</Cliente>
<Portes>SI</Portes>
</Cabecera>
<Detalle>
<Linea>
<Articulo>Ar654</Articulo>
<Cantidad>12</Cantidad>
<Precio>2</Precio>
</Linea>
<Linea>
<Articulo>Ar670</Articulo>
<Cantidad>9</Cantidad>
<Precio>1.21</Precio>
</Linea>
<Linea>
<Articulo>Ar100</Articulo>
<Cantidad>2</Cantidad>
<Precio>3.45</Precio>
</Linea>
<Linea>
<Articulo>Ar999</Articulo>
<Cantidad>215</Cantidad>
<Precio>12.24</Precio>
</Linea>
</Detalle>
</Pedido>
<Pedido>
<Cabecera>
<Numero>35</Numero>
<Fecha>29-abr-2015</Fecha>
<Cliente>
<Nombre>Manuel Enriquez Sousa</Nombre>
<Codigo>CL160</Codigo>
</Cliente>
<Portes>NO</Portes>
</Cabecera>
<Detalle>
<Linea>
<Articulo>Ar003</Articulo>
<Cantidad>10</Cantidad>
<Precio>2.21</Precio>
</Linea>
<Linea>
<Articulo>Ar005</Articulo>
<Cantidad>8</Cantidad>
<Precio>1.28</Precio>
</Linea>
<Linea>
<Articulo>Ar100</Articulo>
<Cantidad>5</Cantidad>
<Precio>3.75</Precio>
</Linea>
</Detalle>
</Pedido>
</Pedidos>
</Document>
Is Output:
<?xml version="1.0" encoding="UTF-8"?>
<dataroot generated="2015-08-22T13:10:05" xmlns:od="urn:schemas-microsoft-com:officedata">
<importarxml>
<Vendedor>Juan Garcia Sanchez</Vendedor>
<idVendedor>VE144</idVendedor>
<FechaFichero>30-abr-2015</FechaFichero>
<Pedido>34</Pedido>
<Fecha>28-abr-2015</Fecha>
<Cliente>Antonio Lopez Martin</Cliente>
<idCliente>CL121</idCliente>
<Portes>SI</Portes>
<Articulo>Ar100</Articulo>
<Cantidad>5</Cantidad>
<Precio>3.75</Precio>
</importarxml>
<importarxml>
<Vendedor>Juan Garcia Sanchez</Vendedor>
<idVendedor>VE144</idVendedor>
<FechaFichero>30-abr-2015</FechaFichero>
<Pedido>34</Pedido>
<Fecha>28-abr-2015</Fecha>
<Cliente>Antonio Lopez Martin</Cliente>
<idCliente>CL121</idCliente>
<Portes>SI</Portes>
<Articulo>Ar005</Articulo>
<Cantidad>8</Cantidad>
<Precio>1.28</Precio>
</importarxml>
<importarxml>
<Vendedor>Juan Garcia Sanchez</Vendedor>
<idVendedor>VE144</idVendedor>
<FechaFichero>30-abr-2015</FechaFichero>
<Pedido>34</Pedido>
<Fecha>28-abr-2015</Fecha>
<Cliente>Antonio Lopez Martin</Cliente>
<idCliente>CL121</idCliente>
<Portes>SI</Portes>
<Articulo>Ar003</Articulo>
<Cantidad>10</Cantidad>
<Precio>2.21</Precio>
</importarxml>
<importarxml>
<Vendedor>Juan Garcia Sanchez</Vendedor>
<idVendedor>VE144</idVendedor>
<FechaFichero>30-abr-2015</FechaFichero>
<Pedido>34</Pedido>
<Fecha>28-abr-2015</Fecha>
<Cliente>Antonio Lopez Martin</Cliente>
<idCliente>CL121</idCliente>
<Portes>SI</Portes>
<Articulo>Ar999</Articulo>
<Cantidad>215</Cantidad>
<Precio>12.24</Precio>
</importarxml>
<importarxml>
<Vendedor>Juan Garcia Sanchez</Vendedor>
<idVendedor>VE144</idVendedor>
<FechaFichero>30-abr-2015</FechaFichero>
<Pedido>35</Pedido>
<Fecha>29-abr-2015</Fecha>
<Cliente>Manuel Enriquez Sousa</Cliente>
<idCliente>CL160</idCliente>
<Portes>No</Portes>
<Articulo>Ar100</Articulo>
<Cantidad>2</Cantidad>
<Precio>3.45</Precio>
</importarxml>
<importarxml>
<Vendedor>Juan Garcia Sanchez</Vendedor>
<idVendedor>VE144</idVendedor>
<FechaFichero>30-abr-2015</FechaFichero>
<Pedido>35</Pedido>
<Fecha>29-abr-2015</Fecha>
<Cliente>Manuel Enriquez Sousa</Cliente>
<idCliente>CL160</idCliente>
<Portes>No</Portes>
<Articulo>Ar670</Articulo>
<Cantidad>9</Cantidad>
<Precio>1.21</Precio>
</importarxml>
<importarxml>
<Vendedor>Juan Garcia Sanchez</Vendedor>
<idVendedor>VE144</idVendedor>
<FechaFichero>30-abr-2015</FechaFichero>
<Pedido>35</Pedido>
<Fecha>29-abr-2015</Fecha>
<Cliente>Manuel Enriquez Sousa</Cliente>
<idCliente>CL160</idCliente>
<Portes>No</Portes>
<Articulo>Ar654</Articulo>
<Cantidad>12</Cantidad>
<Precio>2</Precio>
</importarxml>
</dataroot>
My xslt not work in Pedido Fecha y Cliente:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" />
<xsl:template match="/">
<dataroot xmlns:od="urn:schemas-microsoft-com:officedata" generated="2015-08-22T13:10:05">
<xsl:for-each select="//Document/Pedidos/Pedido/Detalle/Linea">
<xsl:sort select="//Cliente/Nombre" order="descending" />
<importarxml>
<Vendedor>
<xsl:value-of select="//Vendedor/Nombre" />
</Vendedor>
<idVendedor>
<xsl:value-of select="//Vendedor/Codigo" />
</idVendedor>
<FechaFichero>
<xsl:value-of select="//DatosGen/Fecha" />
</FechaFichero>
<Pedido>
<xsl:value-of select="//Cabecera/Numero" />
</Pedido>
<Fecha>
<xsl:value-of select="//Cabecera/Fecha" />
</Fecha>
<Cliente>
<xsl:value-of select="//Cabecera/Cliente/Nombre" />
</Cliente>
<idCliente>
<xsl:value-of select="//Cabecera/Cliente/Codigo" />
</idCliente>
<Portes>
<xsl:value-of select="//Cabecera/Portes" />
</Portes>
<Articulo>
<xsl:value-of select="Articulo" />
</Articulo>
<Cantidad>
<xsl:value-of select="Cantidad" />
</Cantidad>
<Precio>
<xsl:value-of select="Precio" />
</Precio>
</importarxml>
</xsl:for-each>
</dataroot>
</xsl:template>
</xsl:stylesheet>

You don't have your XPath references correct.
Inside your <xsl:for-each>, all paths are relative to the <Linea> nodes, unless you write absolute paths (paths starting with a /). This is also your main mistake: Absolute paths have no context, therefore they select different nodes than you might want.
To access the vendor name with a relative path it would be required to go up four levels first:
<xsl:value-of select="../../../../DatosGen/Vendedor/Nombre" />
Since this is difficult to follow, it's clearer to use the ancestor axis:
<xsl:value-of select="ancestor::Document[1]/DatosGen/Vendedor/Nombre" />
But of course there is only one <DatosGen> in your input, so you could use absolute paths as well:
<xsl:value-of select="/Document/DatosGen/Vendedor/Nombre" />
Either way, you need that more than once, so you can create and use a variable, like here:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" />
<xsl:template match="/Document">
<dataroot xmlns:od="urn:schemas-microsoft-com:officedata" generated="2015-08-22T13:10:05">
<xsl:apply-templates select="Pedidos/Pedido/Detalle/Linea">
<xsl:sort select="Cabecera/Cliente/Nombre" order="descending" />
</xsl:apply-templates>
</dataroot>
</xsl:template>
<xsl:template match="Linea">
<xsl:variable name="DatosGen" select="ancestor::Document[1]/DatosGen" />
<xsl:variable name="Cabecera" select="ancestor::Pedido[1]/Cabecera" />
<importarxml>
<Vendedor><xsl:value-of select="$DatosGen/Vendedor/Nombre" /></Vendedor>
<idVendedor><xsl:value-of select="$DatosGen/Vendedor/Codigo" /></idVendedor>
<FechaFichero><xsl:value-of select="$DatosGen/Fecha" /></FechaFichero>
<Pedido><xsl:value-of select="$Cabecera/Numero" /></Pedido>
<Fecha><xsl:value-of select="$Cabecera/Fecha" /></Fecha>
<Cliente><xsl:value-of select="$Cabecera/Cliente/Nombre" /></Cliente>
<idCliente><xsl:value-of select="$Cabecera/Cliente/Codigo" /></idCliente>
<Portes><xsl:value-of select="$Cabecera/Portes" /></Portes>
<Articulo><xsl:value-of select="Articulo" /></Articulo>
<Cantidad><xsl:value-of select="Cantidad" /></Cantidad>
<Precio><xsl:value-of select="Precio" /></Precio>
</importarxml>
</xsl:template>
</xsl:stylesheet>

Related

XML to Fixed Length File Using XSLT (Complex Position Logic)

We have a requirement in which need to convert XML into Fixed Length File.
First record is as header and after that we have actual records..From 2 record onwards we need to apply the logic which is mentioned below:
1.After length 45, consider 10 numbers 0000001000, what ever be the
last digit we need to check and replace by following the below
table:
"For Positive Amount: (0000001000) - (000000100{)
{= 0
A = 1
B = 2
c = 3
D = 4
E = 5
F = 6
G = 7
H = 8
I = 9
I have not that much idea so created the small XSLT , request anyone please help on the same.
Input:
<?xml version='1.0' encoding='utf-8'?>
<ZR>
<INPUT>
<I_FIL>ERES</I_FIL>
</INPUT>
<TABLES>
<T_ER>
<item>
<DATA> HEADER1111111122222222333333344456</DATA>
</item>
<item>
<DATA>778944 D4E2 EA 1234567891 2018-11-060000001000EA
0000000000000100001020D04YA30TRE0000000XXXYYY 300{ P 2018-11-05</DATA>
</item>
<item>
<DATA>987654 D4E2 EA 1987654321 2018-11-060000002001EA
0000000000000100001020D04YA30UUU0000000XXXLRB 100{ P 2018-11-05</DATA>
</item>
.
.
.
.
.
.
.
.
</T_ER>
</TABLES>
</ZR>
XSLT:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fn="http://www.w3.org/2005/xpath-functions" >
<xsl:output omit-xml-declaration="yes"/>
<xsl:param name="break" select="'
'" />
<xsl:template match="/">
<xsl:value-of select="ZR/TABLES/T_ER/item[1]/DATA"/>
<xsl:value-of select="$break" />
</xsl:template>
</xsl:stylesheet>
Expected Output:
HEADER1111111122222222333333344456
778944 D4E2 EA 1234567891 2018-11-06000000100{EA
0000000000000100001020D04YA30TRE0000000XXXYYY 300{ P 2018-11-05
987654 D4E2 EA 1987654321 2018-11-06000000200AEA
0000000000000100001020D04YA30UUU0000000XXXLRB 100{ P 2018-11-05
.
.
.
.
It looks like you just want to replace the 55th character based on your map, so you could do this...
<xsl:template match="/">
<xsl:value-of select="ZR/TABLES/T_ER/item[1]/DATA"/>
<xsl:value-of select="$break" />
<xsl:for-each select="ZR/TABLES/T_ER/item[position() > 1]/DATA">
<xsl:variable name="char" select="substring('{ABCDEFGHI', number(substring(., 55, 1)) + 1, 1)" />
<xsl:value-of select="concat(substring(., 1, 54), $char, substring(., 56))" />
<xsl:value-of select="$break" />
</xsl:for-each>
</xsl:template>
This would work in XSLT 1.0.
An XSLT 2.0 solution could be this...
<xsl:template match="/">
<xsl:value-of select="ZR/TABLES/T_ER/item[1]/DATA,
ZR/TABLES/T_ER/item[position() > 1]/DATA/concat(substring(., 1, 54), substring('{ABCDEFGHI', number(substring(., 55, 1)) + 1, 1), substring(., 56))"
separator="
" />
</xsl:template>
In XSLT 3.0, you could potentially make use of a map with has the advantage of easily being extended if you wanted to consider two or more characters instead:
<xsl:stylesheet version="3.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:map="http://www.w3.org/2005/xpath-functions/map"
xmlns:fn="http://www.w3.org/2005/xpath-functions" >
<xsl:output omit-xml-declaration="yes"/>
<xsl:param name="break" select="'
'" />
<xsl:variable name="chars" as="map(xs:string, xs:string)">
<xsl:map>
<xsl:map-entry key="'0'" select="'{'"/>
<xsl:map-entry key="'1'" select="'A'"/>
<xsl:map-entry key="'2'" select="'B'"/>
<xsl:map-entry key="'3'" select="'C'"/>
<xsl:map-entry key="'4'" select="'D'"/>
<xsl:map-entry key="'5'" select="'E'"/>
<xsl:map-entry key="'6'" select="'F'"/>
<xsl:map-entry key="'7'" select="'G'"/>
<xsl:map-entry key="'8'" select="'H'"/>
<xsl:map-entry key="'9'" select="'I'"/>
</xsl:map>
</xsl:variable>
<xsl:template match="/">
<xsl:value-of select="ZR/TABLES/T_ER/item[1]/DATA,
ZR/TABLES/T_ER/item[position() > 1]/DATA/concat(substring(., 1, 54), $chars(substring(., 55, 1)), substring(., 56))" separator="
" />
</xsl:template>
</xsl:stylesheet>
There's probably a much nicer way in XSLT 3.0, so hopefully Martin Honnen will be along soon to say....
Well, using functions string-length, substring and translate for your specifications it can be achieved as:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fn="http://www.w3.org/2005/xpath-functions">
<xsl:output omit-xml-declaration="yes" />
<xsl:param name="break" select="'
'" />
<xsl:template match="/">
<xsl:value-of select="ZR/TABLES/T_ER/item[1]/DATA" />
<xsl:value-of select="$break" />
<xsl:for-each select="ZR/TABLES/T_ER/item[position() != 1]">
<xsl:variable name="length" select="string-length(substring(DATA,0,46))" />
<xsl:variable name="tenNumbers" select="substring(DATA, ($length + 1), 10)"/>
<xsl:variable name="charToReplace" select="translate(substring($tenNumbers, string-length($tenNumbers), 1),'0123456789','{ABCDEFGHI')" />
<xsl:value-of select="concat(substring(DATA,0,46), substring(DATA, ($length + 1), 9), $charToReplace, substring(DATA,($length+11),(string-length(DATA) + 1)))"/>
<xsl:value-of select="$break" />
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>

Show distinct records, remove duplicates from xml document using xslt

I have an xml document from that I have to remove duplicate <itemGrp> based on
<rateclass> value.
If there are multiple <itemGrp> with the same <rateclass> exclude all except 1 <itemGrp>
Including xml and xslt, The results can be seen at http://www.freeformatter.com/xsl-transformer.html
by pasting the xml and xslt
XSLT:
<xsl:stylesheet version="2.0"
xmlns:a="http://xml.amadeus.com/FQDRES_12_1_1A"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns:vbs="urn:schemas-sqlxml-org:vbs">
<!-- Main Template -->
<xsl:template match="/Responses">
<xsl:element name="Fares">
<xsl:for-each select="./RequestResponse/Fare_DisplayFaresForCityPairReply">
<xsl:for-each select="./a:flightDetails">
<!-- inside each flight details, we want to get all of the item groups-->
<xsl:for-each select="./a:itemGrp">
<!-- if rateclass repeating then skip this record other wise add this record to output file-->
<xsl:element name="Calss">
<xsl:value-of select="./a:fareQualifItem/a:additionalFareDetails/a:rateClass"/>
</xsl:element>
</xsl:for-each>
</xsl:for-each>
</xsl:for-each>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
XML:
<Responses>
<RequestResponse>
<Fare_DisplayFaresForCityPairReply xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<flightDetails xmlns="http://xml.amadeus.com/FQDRES_12_1_1A">
<itemGrp>
<fareQualifItem>
<additionalFareDetails>
<rateClass>XK2DCA</rateClass>
</additionalFareDetails>
<discountDetails>
<fareQualifier>725</fareQualifier>
</discountDetails>
</fareQualifItem>
</itemGrp>
<itemGrp>
<fareQualifItem>
<additionalFareDetails>
<rateClass>XK2DCAB</rateClass>
</additionalFareDetails>
<discountDetails>
<fareQualifier>725</fareQualifier>
</discountDetails>
</fareQualifItem>
</itemGrp>
<itemGrp>
<fareQualifItem>
<additionalFareDetails>
<rateClass>XK2DCA</rateClass>
</additionalFareDetails>
<discountDetails>
<fareQualifier>725</fareQualifier>
</discountDetails>
</fareQualifItem>
</itemGrp>
</flightDetails>
<flightDetails xmlns="http://xml.amadeus.com/FQDRES_12_1_1A">
<itemGrp>
<fareQualifItem>
<additionalFareDetails>
<rateClass>AAXK2DCA</rateClass>
</additionalFareDetails>
<discountDetails>
<fareQualifier>725</fareQualifier>
</discountDetails>
</fareQualifItem>
</itemGrp>
<itemGrp>
<fareQualifItem>
<additionalFareDetails>
<rateClass>BXK2DCAB</rateClass>
</additionalFareDetails>
<discountDetails>
<fareQualifier>725</fareQualifier>
</discountDetails>
</fareQualifItem>
</itemGrp>
<itemGrp>
<fareQualifItem>
<additionalFareDetails>
<rateClass>AAXK2DCA</rateClass>
</additionalFareDetails>
<discountDetails>
<fareQualifier>725</fareQualifier>
</discountDetails>
</fareQualifItem>
</itemGrp>
</flightDetails>
</Fare_DisplayFaresForCityPairReply>
</RequestResponse>
</Responses>
The response is:
<?xml version="1.0" encoding="UTF-8"?>
<Fares>
<Calss>XK2DCA</Calss>
<Calss>XK2DCAB</Calss>
<Calss>XK2DCA</Calss>
<Calss>AAXK2DCA</Calss>
<Calss>BXK2DCAB</Calss>
<Calss>AAXK2DCA</Calss>
</Fares>
What I want is:
<?xml version="1.0" encoding="UTF-8"?>
<Fares>
<Calss>XK2DCA</Calss>
<Calss>XK2DCAB</Calss>
<Calss>AAXK2DCA</Calss>
<Calss>BXK2DCAB</Calss>
</Fares>
Thanks for the answer Michael. could've been solved:
XSLT 1.0
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:a="http://xml.amadeus.com/FQDRES_12_1_1A" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:vbs="urn:schemas-sqlxml-org:vbs" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.0">
<!-- Main Template -->
<xsl:key name="rateClass" match="/Responses/RequestResponse/Fare_DisplayFaresForCityPairReply/a:flightDetails/a:itemGrp/a:fareQualifItem/a:additionalFareDetails/a:rateClass/text()" use="." />
<xsl:template match="/Responses">
<xsl:element name="Fares">
<xsl:for-each select="./RequestResponse/Fare_DisplayFaresForCityPairReply">
<xsl:for-each select="./a:flightDetails">
<!-- inside each flight details, we want to get all of the item groups-->
<xsl:for-each select="./a:itemGrp">
<!-- if rateclass repeating then skip this record other wise add this record to output file-->
<xsl:variable name="ItemGroup_Items" select="." />
<!--<xsl:variable name="rateClass_1" select="./a:fareQualifItem/a:additionalFareDetails/a:rateClass"/>
<xsl:if test="vbs:CheckExists($rateClass_1) = 'FALSE'">-->
<xsl:for-each select="./a:fareQualifItem/a:additionalFareDetails/a:rateClass/text()[generate-id()= generate-id(key('rateClass',.)[1])]">
<xsl:element name="Calss">
<xsl:value-of select="." />
</xsl:element>
<xsl:element name="Value_from_itemGrp">
<xsl:value-of select="($ItemGroup_Items/a:fareQualifItem/a:additionalFareDetails/a:rateClass)"/>
</xsl:element>
</xsl:for-each>
</xsl:for-each>
</xsl:for-each>
</xsl:for-each>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
Given your latest XML input, the expected output can be achieved quite simply by:
XSLT 2.0
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:a="http://xml.amadeus.com/FQDRES_12_1_1A"
exclude-result-prefixes="a">
<xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/>
<xsl:template match="/Responses">
<Fares>
<xsl:for-each select="distinct-values(RequestResponse/Fare_DisplayFaresForCityPairReply/a:flightDetails/a:itemGrp/a:fareQualifItem/a:additionalFareDetails/a:rateClass)">
<Calss>
<xsl:value-of select="."/>
</Calss>
</xsl:for-each>
</Fares>
</xsl:template>
</xsl:stylesheet>

xsl: template and namespaces

My appologies for asking this question again. I know this has been answered here already several times, but it seems that I still don't get it.
My XML (basically the XML output from Open Office draw, here simplified)
<?xml version="1.0" encoding="UTF-8"?>
<office:document xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:presentation="urn:oasis:names:tc:opendocument:xmlns:presentation:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:smil="urn:oasis:names:tc:opendocument:xmlns:smil-compatible:1.0" xmlns:anim="urn:oasis:names:tc:opendocument:xmlns:animation:1.0" xmlns:rpt="http://openoffice.org/2005/report" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:grddl="http://www.w3.org/2003/g/data-view#" xmlns:officeooo="http://openoffice.org/2009/office" xmlns:tableooo="http://openoffice.org/2009/table" xmlns:drawooo="http://openoffice.org/2010/draw" xmlns:calcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0" xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" xmlns:formx="urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0" xmlns:css3t="http://www.w3.org/TR/css3-text/" office:version="1.2" office:mimetype="application/vnd.oasis.opendocument.graphics">
<office:body>
<office:drawing>
<draw:page draw:name="page1" draw:master-page-name="Standard">
<draw:connector draw:type="curve" draw:start-shape="id1" draw:end-shape="id2" />
<draw:connector draw:type="curve" draw:start-shape="id2" draw:end-shape="id3" />
<draw:connector draw:type="curve" draw:start-shape="id3" draw:end-shape="id4" />
<draw:connector draw:type="curve" draw:start-shape="id1" draw:end-shape="id4" />
<draw:connector draw:type="curve" draw:start-shape="id1" draw:end-shape="id3" />
<draw:custom-shape >
<text:p >
<text:span >AAAA,</text:span>
</text:p>
</draw:custom-shape>
<draw:custom-shape draw:id="id1" >
<text:p >
<text:span >BBBBB</text:span>
</text:p>
</draw:custom-shape>
<draw:custom-shape draw:id="id2" >
<text:p >
<text:span >CCCCC.</text:span>
</text:p>
</draw:custom-shape>
<draw:custom-shape draw:id="id3" >
<text:p >
<text:span >DDDDDDDDDD</text:span>
</text:p>
</draw:custom-shape>
<draw:custom-shape draw:id="id4" >
<text:p >
<text:span >EEEEEEEEEE</text:span>
</text:p>
</draw:custom-shape>
</draw:page>
</office:drawing>
</office:body>
</office:document>
Now I try to convert this (to graphml for yEd) using
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0"
xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0"
xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0"
xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0"
xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0"
xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0"
xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0"
xmlns:presentation="urn:oasis:names:tc:opendocument:xmlns:presentation:1.0"
xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0"
xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0"
xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0"
xmlns:math="http://www.w3.org/1998/Math/MathML"
xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0"
xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0"
xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0"
xmlns:ooo="http://openoffice.org/2004/office"
xmlns:ooow="http://openoffice.org/2004/writer"
xmlns:oooc="http://openoffice.org/2004/calc"
xmlns:dom="http://www.w3.org/2001/xml-events"
xmlns:xforms="http://www.w3.org/2002/xforms"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:smil="urn:oasis:names:tc:opendocument:xmlns:smil-compatible:1.0"
xmlns:anim="urn:oasis:names:tc:opendocument:xmlns:animation:1.0"
xmlns:rpt="http://openoffice.org/2005/report"
xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2"
xmlns:xhtml="http://www.w3.org/1999/xhtml"
xmlns:grddl="http://www.w3.org/2003/g/data-view#"
xmlns:officeooo="http://openoffice.org/2009/office"
xmlns:tableooo="http://openoffice.org/2009/table"
xmlns:drawooo="http://openoffice.org/2010/draw"
xmlns:calcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0"
xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0"
xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0"
xmlns:formx="urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0"
xmlns:css3t="http://www.w3.org/TR/css3-text/">
<xsl:template match="/"> <!-- graphml xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd" xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:java="http://www.yworks.com/xml/yfiles-common/1.0/java" xmlns:sys="http://www.yworks.com/xml/yfiles-common/markup/primitives/2.0" xmlns:x="http://www.yworks.com/xml/yfiles-common/markup/2.0" xmlns:y="http://www.yworks.com/xml/graphml" xmlns:yed="http://www.yworks.com/xml/yed/3" -->
<graphml xmlns:x="http://www.yworks.com/xml/yfiles-common/markup/2.0" xmlns:yed="http://www.yworks.com/xml/yed/3" xmlns:java="http://www.yworks.com/xml/yfiles-common/1.0/java" xmlns:h="http://graphml.graphdrawing.org/xmlns" xmlns:sys="http://www.yworks.com/xml/yfiles-common/markup/primitives/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:y="http://www.yworks.com/xml/graphml" xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd" exclude-result-prefixes="h">
<key for="node" id="d6" yfiles.type="nodegraphics"/>
<key for="port" id="d2" yfiles.type="portuserdata"/>
<key attr.name="N_In" attr.type="int" for="node" id="d3">
<default>0</default>
</key>
<graph id="G" edgedefault="directed">
====================================
<xsl:for-each select="//draw:custom-shape|//draw:frame">
+++++++++++++++++++++++++++++++++++++++++
<xsl:element name="node">
<xsl:attribute name="id">
<xsl:value-of select="#draw:id"/>
</xsl:attribute>
<xsl:variable name="my_node" select="#draw:id"/><!-- xsl:value-of select="$my_node"/ -->
<xsl:element name="data">
<xsl:attribute name="key">d4</xsl:attribute>
<xsl:value-of select="count(//draw:connector[#draw:start-shape=$my_node])"/>
</xsl:element>
<xsl:element name="data">
<xsl:attribute name="key">d3</xsl:attribute>
<xsl:value-of select="count(//draw:connector[#draw:end-shape=$my_node])"/>
</xsl:element>
<xsl:element name="data">
<xsl:attribute name="key">d5</xsl:attribute>
<xsl:value-of select="count(//draw:connector[#draw:start-shape=$my_node])-count(//draw:connector[#draw:end-shape=$my_node])"/>
</xsl:element>
<xsl:apply-templates select="h:In_Counts"/>
<xsl:call-template name="h:In_Counts" />
</xsl:element>
</xsl:for-each>
</graph>
</graphml>
</xsl:template>
<xsl:template match="h:In_Counts" >
in in_counts ------------------------------------------
</xsl:template>
</xsl:stylesheet>
My issue:
I still dont get the (sub)template matched.
Where is the knot in my thinking?
Thank in advance!
Several problems there:
The "h" namespace is not defined.
The <xsl:apply-templates select="h:In_Counts"/> would not match because there are no <In_Counts> elements in the XML file.
The <xsl:call-template name="h:In_Counts"/> fails because there is no <xsl:template name="h:In_Counts"> (note the name attribute).

Namespace issue in xslt

I am trying to convert following xml into other xml but I am not getting the values for xCoordinate and yCoordinate. I would like to convert the structure from source - XML to Target-XML where the goocodes will match and the result would be assigned to x and y.
Source - XML
<?xml version="1.0"?>
<AddressResponse xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" errorCode="0" errorDescription="">
<wrappedResultList xmlns="http://xlocate.xserver.ptvag.com">
<ResultAddress city="Amsterdam" city2="" country="NL" houseNumber="" postCode="1***" state="Noord-Holland" street="" adminRegion="Amsterdam" appendix="" classificationDescription="EXACT" countryCapital="Amsterdam" detailLevelDescription="CITY" totalScore="100">
<wrappedAdditionalFields />
<coordinates>
<kml xsi:nil="true" xmlns="http://common.xserver.ptvag.com" />
<point x="4.89327999999999" y="52.373090000000005" xmlns="http://common.xserver.ptvag.com" />
</coordinates>
</ResultAddress>
<ResultAddress city="Amsterdam-Zuidoost" city2="" country="NL" houseNumber="" postCode="110*" state="Noord-Holland" street="" adminRegion="Amsterdam" appendix="" classificationDescription="EXACT" countryCapital="Amsterdam" detailLevelDescription="CITY" totalScore="80">
<wrappedAdditionalFields />
<coordinates>
<kml xsi:nil="true" xmlns="http://common.xserver.ptvag.com" />
<point x="4.9513699999999838" y="52.316199999999988" xmlns="http://common.xserver.ptvag.com" />
</coordinates>
</ResultAddress>
<ResultAddress city="Nieuw-Amsterdam" city2="" country="NL" houseNumber="" postCode="7833" state="Drenthe" street="" adminRegion="Emmen" appendix="" classificationDescription="EXACT" countryCapital="Amsterdam" detailLevelDescription="CITY" totalScore="80">
<wrappedAdditionalFields />
<coordinates>
<kml xsi:nil="true" xmlns="http://common.xserver.ptvag.com" />
<point x="6.8528699999999994" y="52.716139999999982" xmlns="http://common.xserver.ptvag.com" />
</coordinates>
</ResultAddress>
</wrappedResultList>
</AddressResponse>
Target - XML
<GeoCodeResponse>
<geocordinate>
<xCordinate>4.89327999999999</xCordinate>
<yCordinate>52.716139999999982</yCordinate>
</geocordinate>
</GeoCodeResponse>
XSLT
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xl="http://xlocate.xserver.ptvag.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema" xmlns:xsd="http://www.w3.org/2001/XMLSchema-instance" xmlns:cm="http://common.xserver.ptvag.com" exclude-result-prefixes="xl xsi xsd cm" version="1.0">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/">
<GeoCodeResponse xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<geocordinate xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<xsl:for-each select="AddressResponse/xl:wrappedResultList/xl:ResultAddress">
<xsl:sort select="#xl:totalScore" order="descending" data-type="number"/>
<xsl:if test="position()= 1">
<xCordinate> <xsl:value-of select="/xl:coordinates/cm:point/cm:x" /></xCordinate>
<yCordinate> <xsl:value-of select="/xl:coordinates/cm:point/cm:y" /></yCordinate>
</xsl:if>
</xsl:for-each>
</geocordinate>
</GeoCodeResponse>
</xsl:template>
</xsl:stylesheet>
Please help what could be done in above xslt.
You were almost there. The coordinates are attributes, not nodes.
change it into this:
<xsl:if test="position()= 1">
<xCordinate>
<xsl:value-of select="xl:coordinates/cm:point/#x" />
</xCordinate>
<yCordinate>
<xsl:value-of select="xl:coordinates/cm:point/#y" />
</yCordinate>
</xsl:if>
You are also referencing the coordinates node from the root, but it should be relative. I changed /xl:coordinaties into xl:coordinates

XSLT Select Only Nodes With Text in a Loop

I would like to select only nodes containing text nodes. But when I test for text() parent nodes that contain child nodes with text get returned also. I tried to check by
string-length() but the parent nodes are returning a string length greater than 0.
In this scenario I would like to select only
SendDate
FirstName
LastName
Company
Street
City
State
Zip
Thanks
XML
<BusinessLetter>
<Head>
<SendDate>November 29, 2005</SendDate>
<Recipient>
<Name Title="Mr.">
<FirstName>Joshua</FirstName>
<LastName>Lockwood</LastName>
</Name>
<Company>Lockwood & Lockwood</Company>
<Address>
<Street>291 Broadway Ave.</Street>
<City>New York</City>
<State>NY</State>
<Zip>10007</Zip>
<Country>United States</Country>
</Address>
</Recipient>
</Head>
</BusinessLetter>
XSL
<?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="yes"/>
<xsl:template match="/">
<xsl:for-each select="//*[text()]">
<xsl:if test="text()">
<Match>
<xsl:value-of select="name()"/>:
<xsl:value-of select="string-length(text())"/>
</Match>
<br />
</xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
OUTPUT
BusinessLetter: 2
Head: 3
SendDate: 17
Recipient: 4
Name: 5
FirstName:6
LastName:8
Company:19
Address:5
Street:17
City:8
State:2
Zip:5
Country:13
You are experience a problem with white space only text nodes...
Solution preserving white space only text nodes (better when processing (X)HTML ):
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="*[text()[normalize-space()]]">
<Match>
<xsl:value-of select="concat(name(),
' : ',
string-length(normalize-space()))"/>
</Match>
<br />
</xsl:template>
</xsl:stylesheet>
Output:
<Match>SendDate : 17</Match>
<br />
<Match>FirstName : 6</Match>
<br />
<Match>LastName : 8</Match>
<br />
<Match>Company : 19</Match>
<br />
<Match>Street : 17</Match>
<br />
<Match>City : 8</Match>
<br />
<Match>State : 2</Match>
<br />
<Match>Zip : 5</Match>
<br />
<Match>Country : 13</Match>
<br />
Good question. I spent a few days looking for an answer.
<xsl:value-of select="string-length(normalize-space(text()[1]))" />
This problem is caused by the fact that the white-space-only text nodes are also considered.
Solution:
Include this global (best place is before any <xsl:template>) directive:
<xsl:strip-space elements="*"/>
This instructs the XSLT processor to strip-off the white-space-only text-node children of any (*) element in the XML document.
So, your fixed transformation now is:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/">
<xsl:for-each select="//*[text()]">
<xsl:if test="text()">
<Match>
<xsl:value-of select="name()"/>:
<xsl:value-of select="string-length(text())"/>
</Match>
<br />
</xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
and when applied on the provided XML document:
<BusinessLetter>
<Head>
<SendDate>November 29, 2005</SendDate>
<Recipient>
<Name Title="Mr.">
<FirstName>Joshua</FirstName>
<LastName>Lockwood</LastName>
</Name>
<Company>Lockwood & Lockwood</Company>
<Address>
<Street>291 Broadway Ave.</Street>
<City>New York</City>
<State>NY</State>
<Zip>10007</Zip>
<Country>United States</Country>
</Address>
</Recipient>
</Head>
</BusinessLetter>
the wanted, correct result is produced:
<Match>SendDate:
17
</Match><br><Match>FirstName:
6
</Match><br><Match>LastName:
8
</Match><br><Match>Company:
19
</Match><br><Match>Street:
17
</Match><br><Match>City:
8
</Match><br><Match>State:
2
</Match><br><Match>Zip:
5
</Match><br><Match>Country:
13
</Match><br>