I'm trying to write xslt transformation for xml files and I have a problem with namespace URI-s. Input files has for the same namespace (gml) different URI-s and than it results in "double" namespace declaration - one in root element with one URI value and than in some inline elements with another URI value. I think real example will shows more:
XSLT:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:gco="http://www.isotc211.org/2005/gco" xmlns:gfc="http://www.isotc211.org/2005/gfc" xmlns:gmd="http://www.isotc211.org/2005/gmd" xmlns:gmx="http://www.isotc211.org/2005/gmx" xmlns:gsr="http://www.isotc211.org/2005/gsr" xmlns:gss="http://www.isotc211.org/2005/gss" xmlns:gts="http://www.isotc211.org/2005/gts" xmlns:srv="http://www.isotc211.org/2005/srv" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.0" xsi:schemaLocation=" http://www.isotc211.org/2005/gmd https://inspire.ec.europa.eu/draft-schemas/inspire-md-schemas-temp/apiso-inspire/apiso-inspire.xsd">
<xsl:output method="xml" encoding="UTF-8" indent="yes"/>
<!-- globálne premenné -->
<xsl:variable name="lowercase" select="'aábcdefghíijklmnňopqrstuúvwxyžz'" />
<xsl:variable name="uppercase" select="'AÁBCDEFGHIÍJKLMNŇOPQRSTUÚVWXYŽZ'" />
<!-- hierarchyLevel -->
<xsl:variable name="hierarchyLevel">
<xsl:if test="//gmd:hierarchyLevel/gmd:MD_ScopeCode/#codeListValue = 'service'">
<xsl:value-of select="'service'" />
</xsl:if>
</xsl:variable>
<!-- serviceType -->
<xsl:variable name="serviceType">
<xsl:value-of select="//gmd:identificationInfo/srv:SV_ServiceIdentification/srv:serviceType/gco:LocalName/text()"/>
</xsl:variable>
<!-- Templates -->
<!-- Skopirovanie celeho mtd zaznamu -->
<xsl:template name="HeaderTemplate" match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#* | node()" />
</xsl:copy>
</xsl:template>
<!-- úprava referencii na schemy -->
<xsl:template match="#xsi:schemaLocation"/>
<xsl:template name="Namespaces" match="//gmd:MD_Metadata">
<xsl:choose>
<xsl:when test=" $hierarchyLevel = 'service'">
<gmd:MD_Metadata xsi:schemaLocation="http://www.isotc211.org/2005/srv http://inspire.ec.europa.eu/draft-schemas/inspire-md-schemas-temp/apiso-inspire/apiso-inspire.xsd">
<xsl:apply-templates select="#* | node()" />
</gmd:MD_Metadata>
</xsl:when>
<xsl:otherwise>
<gmd:MD_Metadata xsi:schemaLocation="http://www.isotc211.org/2005/gmd https://inspire.ec.europa.eu/draft-schemas/inspire-md-schemas-temp/apiso-inspire/apiso-inspire.xsd">
<xsl:apply-templates select="#* | node()" />
</gmd:MD_Metadata>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<!-- Kľúčové slová INSPIRE GEMET -->
<xsl:template match="//gmd:descriptiveKeywords/gmd:MD_Keywords[gmd:thesaurusName/gmd:CI_Citation/gmd:title/gco:CharacterString[starts-with(.,'GEMET - INSPIRE themes')]]">
<gmd:MD_Keywords>
<xsl:for-each select="gmd:keyword">
<gmd:keyword>
<xsl:if test="gco:CharacterString = 'Atmospheric conditions'">
<gmx:Anchor xlink:href="http://inspire.ec.europa.eu/theme/ac">Atmosférické podmienky</gmx:Anchor>
</xsl:if>
<xsl:if test="gco:CharacterString = 'Atmosférické podmienky'">
<gmx:Anchor xlink:href="http://inspire.ec.europa.eu/theme/ac">Atmosférické podmienky</gmx:Anchor>
</xsl:if>
</gmd:keyword>
</xsl:for-each>
<gmd:thesaurusName>
<gmd:CI_Citation>
<gmd:title>
<gmx:Anchor xlink:href="https://www.eionet.europa.eu/gemet/it/inspire-themes/">GEMET - INSPIRE themes, version 1.0</gmx:Anchor>
</gmd:title>
<gmd:date>
<gmd:CI_Date>
<gmd:date>
<gco:Date>2008-06-01</gco:Date>
</gmd:date>
<gmd:dateType>
<gmd:CI_DateTypeCode codeList="http://standards.iso.org/iso/19139/resources/gmxCodelists.xml#CI_DateTypeCode" codeListValue="publication"/>
</gmd:dateType>
</gmd:CI_Date>
</gmd:date>
</gmd:CI_Citation>
</gmd:thesaurusName>
</gmd:MD_Keywords>
</xsl:template></xsl:stylesheet>
Input files 1 which has namespace declaration for gml same as XSLT xmlns:gml="http://www.opengis.net/gml/3.2" :
<gmd:MD_Metadata xmlns:gco="http://www.isotc211.org/2005/gco" xmlns:gmd="http://www.isotc211.org/2005/gmd" xmlns:gml="http://www.opengis.net/gml/3.2" xmlns:srv="http://www.isotc211.org/2005/srv" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.isotc211.org/2005/gmd http://inspire.ec.europa.eu/draft-schemas/inspire-md-schemas-temp/apiso-inspire/apiso-inspire.xsd">
<gmd:fileIdentifier>
<gco:CharacterString>https://data.gov.sk/set/rpi/gmd/17316219/SK_UGKK_ZBGIS_INSPIRE_TN</gco:CharacterString>
</gmd:fileIdentifier>
<gmd:language>
<gmd:LanguageCode codeList="http://www.loc.gov/standards/iso639-2/" codeListValue="slo">slo</gmd:LanguageCode>
</gmd:language>
<gmd:hierarchyLevel>
<gmd:MD_ScopeCode codeList="http://standards.iso.org/iso/19139/resources/gmxCodelists.xml#MD_ScopeCode" codeListValue="dataset">dataset</gmd:MD_ScopeCode>
</gmd:hierarchyLevel>
<gmd:contact>
<gmd:CI_ResponsibleParty>
<gmd:organisationName>
<gco:CharacterString>Geodetický a kartografický ústav Bratislava (GKÚ)</gco:CharacterString>
</gmd:organisationName>
<gmd:role>
<gmd:CI_RoleCode codeList="http://standards.iso.org/iso/19139/resources/gmxCodelists.xml#CI_RoleCode" codeListValue="pointOfContact">pointOfContact</gmd:CI_RoleCode>
</gmd:role>
</gmd:CI_ResponsibleParty>
</gmd:contact>
<gmd:dateStamp>
<gco:Date>2019-12-09</gco:Date>
</gmd:dateStamp>
<gmd:metadataStandardName>
<gco:CharacterString>ISO19115 - profil ZBGIS</gco:CharacterString>
</gmd:metadataStandardName>
<gmd:metadataStandardVersion>
<gco:CharacterString>2003/Cor.1:2006</gco:CharacterString>
</gmd:metadataStandardVersion>
<gmd:identificationInfo>
<gmd:MD_DataIdentification>
<gmd:citation>
<gmd:CI_Citation>
<gmd:title>
<gco:CharacterString>INSPIRE - Dopravné siete</gco:CharacterString>
</gmd:title>
<gmd:date>
<gmd:CI_Date>
<gmd:date>
<gco:Date>2017-11-23</gco:Date>
</gmd:date>
<gmd:dateType>
<gmd:CI_DateTypeCode codeList="http://standards.iso.org/iso/19139/resources/gmxCodelists.xml#CI_DateTypeCode" codeListValue="revision">revision</gmd:CI_DateTypeCode>
</gmd:dateType>
</gmd:CI_Date>
</gmd:date>
<gmd:identifier>
<gmd:MD_Identifier>
<gmd:code>
<gco:CharacterString>https://data.gov.sk/set/rpi/dat/17316219/SK_UGKK_ZBGIS_INSPIRE_TN</gco:CharacterString>
</gmd:code>
</gmd:MD_Identifier>
</gmd:identifier>
</gmd:CI_Citation>
</gmd:citation>
<gmd:abstract>
<gco:CharacterString>Dátová sada INSPIRE - Dopravné siete obsahuje vybrané triedy objektov zo ZBGIS, ktoré patria pod dátovú špecifikáciu INSPIRE Transport Networks. Predmetom tejto INSPIRE témy sú siete cestnej, železničnej, leteckej a vodnej dopravy a súvisiaca infraštruktúra.</gco:CharacterString>
</gmd:abstract>
<gmd:pointOfContact>
<gmd:CI_ResponsibleParty>
<gmd:organisationName>
<gco:CharacterString>Geodetický a kartografický ústav Bratislava (GKÚ)</gco:CharacterString>
</gmd:organisationName>
<gmd:role>
<gmd:CI_RoleCode codeList="http://standards.iso.org/iso/19139/resources/gmxCodelists.xml#CI_RoleCode" codeListValue="author">author</gmd:CI_RoleCode>
</gmd:role>
</gmd:CI_ResponsibleParty>
</gmd:pointOfContact>
<gmd:descriptiveKeywords>
<gmd:MD_Keywords>
<gmd:keyword>
<gco:CharacterString>doprava</gco:CharacterString>
</gmd:keyword>
</gmd:MD_Keywords>
</gmd:descriptiveKeywords>
<gmd:spatialRepresentationType>
<gmd:MD_SpatialRepresentationTypeCode codeList="http://standards.iso.org/iso/19139/resources/gmxCodelists.xml#MD_SpatialRepresentationTypeCode" codeListValue="vector">vector</gmd:MD_SpatialRepresentationTypeCode>
</gmd:spatialRepresentationType>
<gmd:spatialResolution>
<gmd:MD_Resolution>
<gmd:equivalentScale>
<gmd:MD_RepresentativeFraction>
<gmd:denominator>
<gco:Integer>10000</gco:Integer>
</gmd:denominator>
</gmd:MD_RepresentativeFraction>
</gmd:equivalentScale>
</gmd:MD_Resolution>
</gmd:spatialResolution>
<gmd:language>
<gmd:LanguageCode codeList="http://www.loc.gov/standards/iso639-2/" codeListValue="slo">slo</gmd:LanguageCode>
</gmd:language>
<gmd:characterSet>
<gmd:MD_CharacterSetCode codeList="http://standards.iso.org/iso/19139/resources/gmxCodelists.xml#MD_CharacterSetCode" codeListValue="utf8">utf8</gmd:MD_CharacterSetCode>
</gmd:characterSet>
<gmd:topicCategory>
<gmd:MD_TopicCategoryCode>transportation</gmd:MD_TopicCategoryCode>
</gmd:topicCategory>
<gmd:extent>
<gmd:EX_Extent>
<gmd:description>
<gco:CharacterString>Územie celej Slovenskej republiky.</gco:CharacterString>
</gmd:description>
<gmd:geographicElement>
<gmd:EX_GeographicBoundingBox>
<gmd:extentTypeCode>
<gco:Boolean>true</gco:Boolean>
</gmd:extentTypeCode>
<gmd:westBoundLongitude>
<gco:Decimal>16.83</gco:Decimal>
</gmd:westBoundLongitude>
<gmd:eastBoundLongitude>
<gco:Decimal>22.57</gco:Decimal>
</gmd:eastBoundLongitude>
<gmd:southBoundLatitude>
<gco:Decimal>47.73</gco:Decimal>
</gmd:southBoundLatitude>
<gmd:northBoundLatitude>
<gco:Decimal>49.61</gco:Decimal>
</gmd:northBoundLatitude>
</gmd:EX_GeographicBoundingBox>
</gmd:geographicElement>
</gmd:EX_Extent>
</gmd:extent>
<gmd:extent>
<gmd:EX_Extent>
<gmd:temporalElement>
<gmd:EX_TemporalExtent>
<gmd:extent>
<gml:TimePeriod gml:id="ID5etd6b9e-f6be-4a4d-b558-1b5c565ba0fe" xsi:type="gml:TimePeriodType">
<gml:beginPosition>2020-01-01</gml:beginPosition>
<gml:endPosition>2020-02-02</gml:endPosition>
</gml:TimePeriod>
</gmd:extent>
</gmd:EX_TemporalExtent>
</gmd:temporalElement>
</gmd:EX_Extent>
</gmd:extent>
</gmd:MD_DataIdentification>
</gmd:identificationInfo></gmd:MD_Metadata>
Second input files which has different uri value for gml namespace xmlns:gml="http://www.opengis.net/gml" :
<gmd:MD_Metadata xmlns:gmd="http://www.isotc211.org/2005/gmd" xmlns:gco="http://www.isotc211.org/2005/gco" xmlns:gts="http://www.isotc211.org/2005/gts" xmlns:gmx="http://www.isotc211.org/2005/gmx" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:gml="http://www.opengis.net/gml" xmlns:xlink="http://www.w3.org/1999/xlink" xsi:schemaLocation="http://www.isotc211.org/2005/gmd http://www.isotc211.org/2005/gmd/metadataEntity.xsd">
<gmd:fileIdentifier>
<gco:CharacterString>https://data.gov.sk/set/rpi/gmd/42181810/4E93317B0429510DE0530210000A9EA5</gco:CharacterString>
</gmd:fileIdentifier>
<gmd:language>
<gmd:LanguageCode codeList="http://www.loc.gov/standards/iso639-2/" codeListValue="slo">slo</gmd:LanguageCode>
</gmd:language>
<gmd:hierarchyLevel>
<gmd:MD_ScopeCode codeList="https://standards.iso.org/ittf/PubliclyAvailableStandards/ISO_19139_Schemas/resources/codelist/ML_gmxCodelists.xml#MD_ScopeCode" codeListValue="dataset">dataset</gmd:MD_ScopeCode>
</gmd:hierarchyLevel>
<gmd:contact>
<gmd:CI_ResponsibleParty>
<gmd:individualName>
<gco:CharacterString>Martin Tuchyňa</gco:CharacterString>
</gmd:individualName>
<gmd:organisationName>
<gco:CharacterString>Ministerstvo životného prostredia Slovenskej republiky</gco:CharacterString>
</gmd:organisationName>
<gmd:role>
<gmd:CI_RoleCode codeList="https://standards.iso.org/ittf/PubliclyAvailableStandards/ISO_19139_Schemas/resources/codelist/ML_gmxCodelists.xml#CI_RoleCode" codeListValue="pointOfContact">pointOfContact</gmd:CI_RoleCode>
</gmd:role>
</gmd:CI_ResponsibleParty>
</gmd:contact>
<gmd:dateStamp>
<gco:Date>2017-05-03</gco:Date>
</gmd:dateStamp>
<gmd:metadataStandardName>
<gco:CharacterString>ISO 19115</gco:CharacterString>
</gmd:metadataStandardName>
<gmd:metadataStandardVersion>
<gco:CharacterString>2003/Cor.1:2006, Slovenský národný metaúdajový profil</gco:CharacterString>
</gmd:metadataStandardVersion>
<gmd:identificationInfo>
<gmd:MD_DataIdentification>
<gmd:citation>
<gmd:CI_Citation>
<gmd:title>
<gco:CharacterString>INSPIRE PD 1,01 Zóny hodnotenia a riadenia kvality ovzdušia, Aglomerácie hodnotenia a riadenia kvality ovzdušia</gco:CharacterString>
</gmd:title>
<gmd:date>
<gmd:CI_Date>
<gmd:date>
<gco:Date>2017-05-01</gco:Date>
</gmd:date>
<gmd:dateType>
<gmd:CI_DateTypeCode codeList="https://standards.iso.org/ittf/PubliclyAvailableStandards/ISO_19139_Schemas/resources/codelist/ML_gmxCodelists.xml#CI_DateTypeCode" codeListValue="creation">creation</gmd:CI_DateTypeCode>
</gmd:dateType>
</gmd:CI_Date>
</gmd:date>
<gmd:identifier>
<gmd:RS_Identifier>
<gmd:code>
<gco:CharacterString>https://data.gov.sk/set/rpi/dat/42181810/4E93317B0429510DE0530210000A9EA5</gco:CharacterString>
</gmd:code>
<gmd:codeSpace>
<gco:CharacterString>https://data.gov.sk/set/rpi/dat/42181810/</gco:CharacterString>
</gmd:codeSpace>
</gmd:RS_Identifier>
</gmd:identifier>
</gmd:CI_Citation>
</gmd:citation>
<gmd:abstract>
<gco:CharacterString>Smernica Európskeho Parlamentu a Rady 2008/50/ES z 21. mája 2008 o kvalite okolitého ovzdušia a čistejšom ovzduší v Európe (vrátane implementácie Rozhodnutia 20111/850/EU);Referencia v legislatíve: Článok 6,27;Informácie o kvalite vonkajšieho ovzdušia a čistejšom ovzduší pre Európu. INSPIRE prioritný dataset (http://inspire-geoportal.ec.europa.eu/thematicviewer/Domain.action?domain=air_noise&national=false&legislationFilter=false&country=SK)</gco:CharacterString>
</gmd:abstract>
<gmd:pointOfContact>
<gmd:CI_ResponsibleParty>
<gmd:individualName>
<gco:CharacterString>Ing. Michal Mladý</gco:CharacterString>
</gmd:individualName>
<gmd:organisationName>
<gco:CharacterString>Slovenský hydrometeorologický ústav</gco:CharacterString>
</gmd:organisationName>
<gmd:role>
<gmd:CI_RoleCode codeList="https://standards.iso.org/ittf/PubliclyAvailableStandards/ISO_19139_Schemas/resources/codelist/ML_gmxCodelists.xml#CI_RoleCode" codeListValue="distributor">distributor</gmd:CI_RoleCode>
</gmd:role>
</gmd:CI_ResponsibleParty>
</gmd:pointOfContact>
<gmd:descriptiveKeywords>
<gmd:MD_Keywords>
<gmd:keyword>
<gco:CharacterString>Directive 2008/50/EC</gco:CharacterString>
</gmd:keyword>
<gmd:keyword>
<gco:CharacterString>Management zones and agglomerations (Air Quality Directive)</gco:CharacterString>
</gmd:keyword>
</gmd:MD_Keywords>
</gmd:descriptiveKeywords>
<gmd:spatialRepresentationType>
<gmd:MD_SpatialRepresentationTypeCode codeListValue="vector" codeList="http://www.isotc211.org/2005/resources/codeList.xml#MD_SpatialRepresentationTypeCode">vector</gmd:MD_SpatialRepresentationTypeCode>
</gmd:spatialRepresentationType>
<gmd:language>
<gmd:LanguageCode codeList="http://www.loc.gov/standards/iso639-2/" codeListValue="slo">slo</gmd:LanguageCode>
</gmd:language>
<gmd:characterSet>
<gmd:MD_CharacterSetCode codeList="https://standards.iso.org/ittf/PubliclyAvailableStandards/ISO_19139_Schemas/resources/codelist/ML_gmx Codelists.xml#MD_ClassificationCode" codeListValue="utf8">utf8</gmd:MD_CharacterSetCode>
</gmd:characterSet>
<gmd:topicCategory>
<gmd:MD_TopicCategoryCode>structure</gmd:MD_TopicCategoryCode>
</gmd:topicCategory>
<gmd:extent>
<gmd:EX_Extent>
<gmd:geographicElement>
<gmd:EX_GeographicBoundingBox>
<gmd:extentTypeCode>
<gco:Boolean>true</gco:Boolean>
</gmd:extentTypeCode>
<gmd:westBoundLongitude>
<gco:Decimal>16.83</gco:Decimal>
</gmd:westBoundLongitude>
<gmd:eastBoundLongitude>
<gco:Decimal>22.57</gco:Decimal>
</gmd:eastBoundLongitude>
<gmd:southBoundLatitude>
<gco:Decimal>47.73</gco:Decimal>
</gmd:southBoundLatitude>
<gmd:northBoundLatitude>
<gco:Decimal>49.61</gco:Decimal>
</gmd:northBoundLatitude>
</gmd:EX_GeographicBoundingBox>
</gmd:geographicElement>
</gmd:EX_Extent>
</gmd:extent>
<gmd:extent>
<gmd:EX_Extent>
<gmd:temporalElement>
<gmd:EX_TemporalExtent>
<gmd:extent>
<gml:TimePeriod gml:id="ID4tre6b9e-f68e-4a4d-b528-1bh5865ba0fe">
<gml:begin>2020-01-01</gml:begin>
<gml:end>2020-02-02</gml:end>
</gml:TimePeriod>
</gmd:extent>
</gmd:EX_TemporalExtent>
</gmd:temporalElement>
</gmd:EX_Extent>
</gmd:extent>
</gmd:MD_DataIdentification>
</gmd:identificationInfo></gmd:MD_Metadata>
The problem is result of XLST transformation of second file which looks like:
<gmd:MD_Metadata xmlns:gml="http://www.opengis.net/gml/3.2"
xmlns:gco="http://www.isotc211.org/2005/gco"
xmlns:gfc="http://www.isotc211.org/2005/gfc"
xmlns:gmd="http://www.isotc211.org/2005/gmd"
xmlns:gmx="http://www.isotc211.org/2005/gmx"
xmlns:gsr="http://www.isotc211.org/2005/gsr"
xmlns:gss="http://www.isotc211.org/2005/gss"
xmlns:gts="http://www.isotc211.org/2005/gts"
xmlns:srv="http://www.isotc211.org/2005/srv"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.isotc211.org/2005/gmd https://inspire.ec.europa.eu/draft-schemas/inspire-md-schemas-temp/apiso-inspire/apiso-inspire.xsd">
<gmd:fileIdentifier xmlns:gml="http://www.opengis.net/gml">
<gco:CharacterString>https://data.gov.sk/set/rpi/gmd/42181810/4E93317B0429510DE0530210000A9EA5</gco:CharacterString>
</gmd:fileIdentifier>
<gmd:language xmlns:gml="http://www.opengis.net/gml">
<gmd:LanguageCode codeList="http://www.loc.gov/standards/iso639-2/" codeListValue="slo">slo</gmd:LanguageCode>
</gmd:language>
<gmd:parentIdentifier xmlns:gml="http://www.opengis.net/gml">
<gco:CharacterString/>
</gmd:parentIdentifier>
<gmd:hierarchyLevel xmlns:gml="http://www.opengis.net/gml">
<gmd:MD_ScopeCode codeList="https://standards.iso.org/ittf/PubliclyAvailableStandards/ISO_19139_Schemas/resources/codelist/ML_gmxCodelists.xml#MD_ScopeCode"
codeListValue="dataset">dataset</gmd:MD_ScopeCode>
</gmd:hierarchyLevel>
<gmd:contact xmlns:gml="http://www.opengis.net/gml">
<gmd:CI_ResponsibleParty>
<gmd:individualName>
As you can see i have double namespace declaration for gml but I just need to have just one at root which is same as in XSLT = xmlns:gml="http://www.opengis.net/gml/3.2" . Please can you help me. Thanks.
Related
I am looking to extract values from an array where each array is connected to a object key name.
The problem I encounter is not knowing how to structure the inner "xsl:foreach" toward a map array.
I will later differentiate the elements by adding attributes but I left that out to keep the question and data at minimal level.
JSON:
<data>
{
"datasheets": {
"balance": {
"cash": [4, 2, 3, 1],
"bank": [5, 8, 7, 9]
}
}
}
</data>
XSL:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:transform version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:docroot="http://www.example.org/1"
xmlns:report="http://www.example.org/2"
xmlns:cells="http://www.example.org/3"
expand-text="yes"
>
<xsl:output method="xml" indent="yes"/>
<xsl:mode on-no-match="shallow-skip"/>
<!-- Parse JSON to XML -->
<xsl:template match="data">
<docroot>
<xsl:apply-templates select="json-to-xml(.)/*"/>
</docroot>
</xsl:template>
<!-- Transform balance data -->
<xsl:template match="*[#key = 'balance']">
<report:yearly-values>
<xsl:for-each select="./*">
<!-- <xsl:for-each select="./*"> -->
<xsl:element name="cells:{#key}">Placeholder</xsl:element>
<!-- </xsl:for-each> -->
</xsl:for-each>
</report:yearly-values>
</xsl:template>
</xsl:transform>
Result:
<?xml version="1.0" encoding="UTF-8"?>
<docroot xmlns:cells="http://www.example.org/3"
xmlns:docroot="http://www.example.org/1"
xmlns:report="http://www.example.org/2">
<report:yearly-values>
<cells:cash>Placeholder</cells:cash>
<cells:bank>Placeholder</cells:bank>
</report:yearly-values>
</docroot>
Wanted result:
<?xml version="1.0" encoding="UTF-8"?>
<docroot xmlns:cells="http://www.example.org/3"
xmlns:docroot="http://www.example.org/1"
xmlns:report="http://www.example.org/2">
<report:yearly-values>
<cells:cash>4</cells:cash>
<cells:cash>2</cells:cash>
<cells:cash>3</cells:cash>
<cells:cash>1</cells:cash>
<cells:bank>5</cells:bank>
<cells:bank>8</cells:bank>
<cells:bank>7</cells:bank>
<cells:bank>9</cells:bank>
</report:yearly-values>
</docroot>
When you first take this debugging step to see what is going on:
<xsl:template match="*[#key = 'balance']">
<report:yearly-values>
<xsl:copy-of select="."/>
</report:yearly-values>
</xsl:template>
Would give this xml-fragment:
<report:yearly-values>
<map xmlns="http://www.w3.org/2005/xpath-functions" key="balance">
<array key="cash">
<number>4</number>
<number>2</number>
<number>3</number>
<number>1</number>
</array>
<array key="bank">
<number>5</number>
<number>8</number>
<number>7</number>
<number>9</number>
</array>
</map>
</report:yearly-values>
Then it is more clear what you need. Take the for-each one level deeper and use the #key of the parent for you element-name, like this:
<xsl:template match="*[#key = 'balance']">
<report:yearly-values>
<xsl:for-each select="*/*">
<xsl:element name="cells:{parent::*/#key}"><xsl:value-of select="text()"/></xsl:element>
</xsl:for-each>
</report:yearly-values>
</xsl:template>
You're just iterating over the two arrays but not the content of the arrays. The following will produce the wanted output:
<xsl:for-each select="./*/*">
<!-- <xsl:for-each select="./*/*"> -->
<xsl:element name="cells:{parent::*/#key}">
<xsl:value-of select="."/>
</xsl:element>
<!-- </xsl:for-each> -->
</xsl:for-each>
i would like to find the highest temperate of the month APRIL, the xml has other month too.
how can i code in my xsl to retrieve the highest temperate?
here is my XML code
<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="THISISA3.xsl"?>
<forecast qTime="28/10/20 10:00 PM" qLocation="Singapore">
<weather yyyymmdd="20200430">
<year>2020</year>
<month>04</month>
<date>30</date>
<comment>Plenty of sunshine</comment>
<code>sunny</code>
<highest>32.6</highest>
<lowest>28.4</lowest>
</weather>
<weather yyyymmdd="20200421">
<year>2020</year>
<month>04</month>
<date>21</date>
<comment>Plenty of sunshine</comment>
<code>sunny</code>
<highest>32.2</highest>
<lowest>29.8</lowest>
</weather>
</forecast>
It is good to provide the required output and also to show the efforts made to get the result as the community here to help with specific problems and not to write the whole code.
However, if you're newbie to start with xslt then below code with comments could help you to get started and to understand the use of stuff in xslt.
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output method="xml" indent="yes"/>
<xsl:strip-space elements="*"/>
<!-- key is used to identify nodes within an expression -->
<xsl:key name="highTemp" match="highest" use="."/>
<!-- identity template to result the transformation in source XML doc itself -->
<xsl:template match="node()|#*">
<xsl:copy>
<xsl:apply-templates select="node()|#*"/>
</xsl:copy>
</xsl:template>
<!-- matching a root node -->
<xsl:template match="forecast">
<!-- iterating through each 'weather' element -->
<xsl:for-each select="weather">
<!-- selecting node which matches the variable having required highest temperature -->
<xsl:apply-templates select=".[highest=$monthApril]"/>
</xsl:for-each>
</xsl:template>
<xsl:variable name="monthApril">
<!-- iterate only 'weather' elements which are from month of April -->
<xsl:for-each select="//weather[substring(#yyyymmdd,5,2) = '04']">
<!-- sorting in descending order so that node having highest temp comes first -->
<xsl:sort select="key('highTemp', highest)" order="descending"/>
<xsl:if test="position()=1">
<xsl:value-of select="highest"/>
</xsl:if>
</xsl:for-each>
</xsl:variable>
</xsl:stylesheet>
It would be nice if you specified what the required output is and how the variables are set and which version of xslt you use.
Below is an example XSLT 1.0 template (it has name 'highestTempForMonth') with the ability to specify the required month (it can be specified in a parameter 'month' for template) and with the ability to call this template with required month in any place you want to do it.
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" >
<xsl:output method="xml" indent="yes" encoding="Utf-8"/>
<xsl:variable name="requiredMonth" select="'04'"/>
<xsl:template match="/">
<HighestTemperature>
<value>
<xsl:call-template name="highestTempForMonth">
<xsl:with-param name="month" select="$requiredMonth"/>
</xsl:call-template>
</value>
</HighestTemperature>
</xsl:template>
<xsl:template name="highestTempForMonth">
<xsl:param name="month"/>
<xsl:for-each select="/forecast/weather[month = $month]/highest">
<xsl:sort select="." data-type="number" order="descending"/>
<xsl:if test="position() = 1"><xsl:value-of select="."/></xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
There is XSLT 2.0 equivalent (with a little bit simpler template part) example.
<?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="#all" version="2.0" >
<xsl:output method="xml" indent="yes" encoding="Utf-8"/>
<xsl:variable name="requiredMonth" select="'04'"/>
<xsl:template match="/">
<HighestTemperature>
<value>
<xsl:call-template name="highestTempForMonth">
<xsl:with-param name="month" select="$requiredMonth"/>
</xsl:call-template>
</value>
</HighestTemperature>
</xsl:template>
<xsl:template name="highestTempForMonth">
<xsl:param name="month"/>
<xsl:value-of select="max(/forecast/weather[month = $month]/highest/xs:double(.))"/>
</xsl:template>
</xsl:stylesheet>
For both examples if there are no values for the specified month, the 'value' tag with an empty value will be specified. This value can be changed by a simple condition if necessary.
I need an XSL solution to replace XML nodes with new nodes.
Say I have the following existing XML structure:
<?xml version="1.0" encoding="UTF-8"?>
<ns0:MT_AvanzarEventoIdCase2_Req_Out xmlns:ns0="http://colpensiones.gov.co/AvanzarEventoIdCase2">
<configuracion>
<tipoSistemaExterno>test4</tipoSistemaExterno>
<tipoProcesamiento>test5</tipoProcesamiento>
<idCorrelacion>test6</idCorrelacion>
</configuracion>
<informacionEventoCasoBPM>
<numeroRadicadoCaso>test</numeroRadicadoCaso>
<nombreEvento>test2</nombreEvento>
<informacionRelacionada>test3</informacionRelacionada>
</informacionEventoCasoBPM>
</ns0:MT_AvanzarEventoIdCase2_Req_Out>
and I need to tranform to this structure:
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:per="http://www.colpensiones.gov.co/contracts/1.0/personas"
xmlns:per1="http://www.colpensiones.gov.co/schemas/1.0/personas"
xmlns:com="http://www.colpensiones.gov.co/contracts/1.0/comun"
xmlns:com1="http://www.colpensiones.gov.co/schemas/1.0/comun">
<soapenv:Header>
<per:Configuracion>
<per1:tipoSistemaExterno>?</per1:tipoSistemaExterno>
<per1:tipoProcesamiento>?</per1:tipoProcesamiento>
<per1:idCorrelacion>?</per1:idCorrelacion>
</per:Configuracion>
</soapenv:Header>
<soapenv:Body>
<com:InformacionEventoCasoBPM>
<com1:numeroRadicadoCaso>?</com1:numeroRadicadoCaso>
<com1:nombreEvento>?</com1:nombreEvento>
<com1:informacionRelacionada>?</com1:informacionRelacionada>
</com:InformacionEventoCasoBPM>
</soapenv:Body>
</soapenv:Envelope>
I'he been trying for 1 week and I couldn't, This was my structure but it didn't work:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:per="http://www.colpensiones.gov.co/contracts/1.0/personas"
xmlns:per1="http://www.colpensiones.gov.co/schemas/1.0/personas"
xmlns:com="http://www.colpensiones.gov.co/contracts/1.0/comun"
xmlns:com1="http://www.colpensiones.gov.co/schemas/1.0/comun"
exclude-result-prefixes="soapenv per per1 com com1">
<xsl:template match = "/">
<soapenv:envelope>
<soapenv:header>
<per:Configuracion>
<per1:tipoSistemaExterno><xsl:value-of select = "tipoSistemaExterno"/></per1:tipoSistemaExterno>
<per1:tipoProcesamiento><xsl:value-of select = "tipoProcesamiento"/></per1:tipoProcesamiento>
<per1:idCorrelacion><xsl:value-of select = "idCorrelacion"/></per1:idCorrelacion>
</per:Configuracion>
</soapenv:header>
<soapenv:body>
<com:InformacionEventoCasoBPM>
<com1:numeroRadicadoCaso><xsl:value-of select = "numeroRadicadoCaso"/></com1:numeroRadicadoCaso>
<com1:nombreEvento><xsl:value-of select = "nombreEvento"/></com1:nombreEvento>
<com1:informacionRelacionada><xsl:value-of select = "informacionRelacionada"/></com1:informacionRelacionada>
</com:InformacionEventoCasoBPM>
</soapenv:body>
</soapenv:envelope>
</xsl:template>
</xsl:stylesheet>
Thank for your help.
I just assumed that you want exactly that output. The code for that would be:
<xsl:template match="/">
<xsl:element name="soapenv-Envelope">
<xsl:element name="soapenv-Header">
<xsl:apply-templates select="//configuracion"/>
</xsl:element>
<xsl:element name="soapenv-Body">
<xsl:apply-templates select="//informacionEventoCasoBPM"/>
</xsl:element>
</xsl:element>
</xsl:template>
<xsl:template match="configuracion">
<xsl:element name="per-Configuration">
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
<xsl:template match="*[ancestor::configuracion]">
<xsl:element name="{concat('per1-', local-name())}">
<!-- copy the text within the node -->
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
<xsl:template match="informacionEventoCasoBPM">
<xsl:element name="com-InformacionEventoCasoBPM">
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
<xsl:template match="*[ancestor::informacionEventoCasoBPM]">
<xsl:element name="{concat('com1-', local-name())}">
<!-- copy the text within the node -->
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
I replaced the : with - though because I did not want to declare new namespaces.
I'm using Saxon Home Edition to convert XML to JSON:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" encoding="UTF-8" />
<xsl:template match="/">
<xsl:variable name="xmljson">
<map xmlns="http://www.w3.org/2005/xpath-functions">
<string key="name">Some name</string>
<string key="description">A nice description</string>
</map>
</xsl:variable>
<xsl:value-of select="xml-to-json($xmljson)" />
</xsl:template>
</xsl:stylesheet>
Produces the desired output:
{"name":"Some name","description":"A nice description"}
The description field contains arbitrary complex xhtml. The template rule does not work with the following description field:
<string key="description">A <strong>nice</strong> description</string>
Error message:
xml-to-json: unknown element <strong>
Enclosing the description in a CDATA section does work:
<string key="description"><![CDATA[A <strong>nice</strong> description]]></string>
Desired output:
{"name":"Some name","description":"A <strong>nice<\/strong> description"}
Problem/Question
The content of the description field is the result of a transformation. So with and withou CDATA fails. This will not work:
<string key="description"><xsl:apply-template select="description" /></string>
Neither this:
<string key="description"><![CDATA[<xsl:apply-template select="description" />]]></string>
Use the serialize() function to produce escaped XML markup as text.
<xsl:variable name="options" as="element()">
<output:serialization-parameters xmlns:output="http://www.w3.org/2010/xslt-xquery-serialization">
<output:omit-xml-declaration value="yes"/>
</output:serialization-parameters>
</xsl:variable>
<xsl:variable name="xmljson" as="element()">
<map xmlns="http://www.w3.org/2005/xpath-functions">
<string key="name">Some name</string>
<string key="description"><xsl:value-of select="serialize(description, $options)"/></string>
</map>
</xsl:variable>
I came up with the following quick hack. Have to check this tomorrow again, kind of tired now...t
Edit: This is a horrible hack! The template rule does not treat special characters. Please read the comments below.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" encoding="UTF-8" />
<xsl:template match="/">
<xsl:variable name="doc">
<description>A <strong class="red">nice</strong> description</description>
</xsl:variable>
<xsl:variable name="xmljson">
<map xmlns="http://www.w3.org/2005/xpath-functions">
<string key="description"><xsl:apply-templates select="$doc/description/text()|$doc/description/*" /></string>
</map>
</xsl:variable>
<xsl:value-of select="xml-to-json($xmljson)" />
</xsl:template>
<xsl:template match="*">
<!-- opening tag -->
<xsl:text><</xsl:text>
<xsl:value-of select="name()"/>
<!-- attribute nodes -->
<xsl:apply-templates select="#*"/>
<xsl:text>></xsl:text>
<xsl:apply-templates/>
<!-- closing tag -->
<xsl:text><</xsl:text>
<xsl:text>/</xsl:text>
<xsl:value-of select="name()"/>
<xsl:text>></xsl:text>
</xsl:template>
<xsl:template match="#*">
<xsl:text> </xsl:text>
<xsl:value-of select="name()"/>
<xsl:text>="</xsl:text>
<xsl:value-of select="." />
<xsl:text>"</xsl:text>
</xsl:template>
</xsl:stylesheet>
Produces the desired output:
{"description":"A <strong class=\"red\">nice<\/strong> description"}
I've got a little tool which strips out and re-arranges an iTunes formatted RSS feed and converts it to a nice simple XML file.
I then import the cleansed XML into mySQL to do things with later.
I need to be able to convert the pubDate in the feed to a mySQL timestamp so I can import this properly into a TIMESTAMP field in my table.
I'm having some issues with it.
My current XSL file does a tidy up on the date, but I don't need this at all.
I just want the <pubDate> node to have the correct mySQL friendly timestamp inside instead.
I've not yet managed to find anything which does what I need. Any pointers?
Here is my XSLT file...
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:atom="http://www.w3.org/2005/Atom"
xmlns:cc="http://web.resource.org/cc/"
xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd"
xmlns:libsyn="http://libsyn.com/rss-extension"
xmlns:media="http://search.yahoo.com/mrss/"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
exclude-result-prefixes="atom cc itunes libsyn media rdf">
<xsl:output method="xml" encoding="UTF-8" indent="yes"/>
<xsl:template match="/">
<data>
<entries>
<xsl:apply-templates select="rss/channel/item"></xsl:apply-templates>
</entries>
</data>
</xsl:template>
<xsl:template match="item">
<entry>
<title><xsl:value-of select="title"/></title>
<link><xsl:value-of select="link"/></link>
<description><xsl:value-of select="description" disable-output-escaping="yes"/></description>
<subtitle><xsl:value-of select="itunes:subtitle"/></subtitle>
<pubDate><xsl:value-of select="pubDate"/></pubDate>
<xsl:apply-templates select="pubDate"/>
<explicit><xsl:value-of select="itunes:explicit"/></explicit>
<podcastImage><xsl:value-of select="itunes:image/#href"/></podcastImage>
<podcastURL><xsl:value-of select="enclosure/#url"/></podcastURL>
<podcastLength><xsl:value-of select="enclosure/#length"/></podcastLength>
<podcastDuration><xsl:value-of select="itunes:duration"/></podcastDuration>
</entry>
</xsl:template>
<xsl:template match="pubDate">
<date>
<xsl:attribute name="time"><xsl:value-of select="substring(text(),18,5)"/></xsl:attribute>
<xsl:call-template name="format-from-rfc-to-iso">
<xsl:with-param name="rfc-date" select="text()"/>
</xsl:call-template>
</date>
</xsl:template>
<xsl:template name="format-from-rfc-to-iso">
<xsl:param name="rfc-date"/>
<xsl:param name="day-with-zero" select="format-number(substring(substring($rfc-date,6,11),1,2),'00')"/>
<xsl:param name="month-with-zero">
<xsl:if test="contains($rfc-date,'Jan')">01</xsl:if>
<xsl:if test="contains($rfc-date,'Feb')">02</xsl:if>
<xsl:if test="contains($rfc-date,'Mar')">03</xsl:if>
<xsl:if test="contains($rfc-date,'Apr')">04</xsl:if>
<xsl:if test="contains($rfc-date,'May')">05</xsl:if>
<xsl:if test="contains($rfc-date,'Jun')">06</xsl:if>
<xsl:if test="contains($rfc-date,'Jul')">07</xsl:if>
<xsl:if test="contains($rfc-date,'Aug')">08</xsl:if>
<xsl:if test="contains($rfc-date,'Sep')">09</xsl:if>
<xsl:if test="contains($rfc-date,'Oct')">10</xsl:if>
<xsl:if test="contains($rfc-date,'Nov')">11</xsl:if>
<xsl:if test="contains($rfc-date,'Dec')">12</xsl:if>
</xsl:param>
<xsl:param name="year-full" select="format-number(substring(substring($rfc-date,6,11),7,5),'####')"/>
<xsl:param name="rfc-date-to-iso" select="concat($year-full,'-',$month-with-zero,'-',$day-with-zero)"/>
<xsl:value-of select="$rfc-date-to-iso"/>
</xsl:template>
</xsl:stylesheet>
The current date/time looks like this from the rss feed:
<pubDate>Sun, 07 Feb 2016 00:00:56 -0500</pubDate>
I'd like it to by displayed like this so it can be inserted into mySQL:
<pubDate>2016-02-07 00:00:56</pubDate>
I use PHP to process this.
$xml = new DOMDocument;
$xml->load('podbean.xml');
$xsl = new DOMDocument;
$xsl->load('podbean.xsl');
// Configure the transformer
$proc = new XSLTProcessor;
$proc->importStyleSheet($xsl); // attach the xsl rules
$proc->transformToXML($xml);
$proc->transformToURI($xml,'itunes.xml');
Simon
Using a processor that supports the EXSLT str:tokenize() function (as libxslt does), you can do something like this:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:str="http://exslt.org/strings"
extension-element-prefixes="str">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<!-- ... -->
<xsl:template match="item">
<entry>
<!-- ... -->
<pubDate>
<xsl:variable name="date-tokens" select="str:tokenize(pubDate, ' ' )" />
<!-- year -->
<xsl:value-of select="$date-tokens[4]" />
<xsl:text>-</xsl:text>
<!-- month -->
<xsl:variable name="mmm" select="$date-tokens[3]" />
<xsl:variable name="m" select="string-length(substring-before('JanFebMarAprMayJunJulAugSepOctNovDec', $mmm)) div 3 + 1" />
<xsl:value-of select="format-number($m, '00')" />
<xsl:text>-</xsl:text>
<!-- day -->
<xsl:value-of select="format-number($date-tokens[2], '00')" />
<xsl:text> </xsl:text>
<!-- time -->
<xsl:value-of select="$date-tokens[5]" />
</pubDate>
<!-- ... -->
</entry>
</xsl:template>
</xsl:stylesheet>