I have the following XML file I need to convert.
Original XML
<xml xmlns:s='uuid:BDC6E3F0-6DA3-11d1-A2A3-00AA00C14882'
xmlns:dt='uuid:C2F41010-65B3-11d1-A29F-00AA00C14882'
xmlns:rs='urn:schemas-microsoft-com:rowset'
xmlns:z='#RowsetSchema'>
<s:Schema id='RowsetSchema'>
<s:ElementType name='row' content='eltOnly'>
<s:AttributeType name='c0' rs:name='v.id_viag' rs:number='1' rs:nullable='true' rs:write='true'>
<s:datatype dt:type='number' rs:dbtype='numeric' dt:maxLength='19' rs:scale='0' rs:precision='19' rs:fixedlength='true'/>
</s:AttributeType>
<s:AttributeType name='c1' rs:name='v.dt_cria' rs:number='2' rs:nullable='true' rs:write='true'>
<s:datatype dt:type='dateTime' rs:dbtype='timestamp' dt:maxLength='16' rs:scale='6' rs:precision='26' rs:fixedlength='true'/>
</s:AttributeType>
<s:AttributeType name='c2' rs:name='v.id_usu_cria' rs:number='3' rs:nullable='true' rs:write='true'>
<s:datatype dt:type='string' rs:dbtype='str' dt:maxLength='255'/>
</s:AttributeType>
<s:AttributeType name='c3' rs:name='v.dt_ult_atualz' rs:number='4' rs:nullable='true' rs:write='true'>
<s:datatype dt:type='dateTime' rs:dbtype='timestamp' dt:maxLength='16' rs:scale='6' rs:precision='26' rs:fixedlength='true'/>
</s:AttributeType>
<s:AttributeType name='c4' rs:name='v.id_usu_ult_atualz' rs:number='5' rs:nullable='true' rs:write='true'>
<s:datatype dt:type='string' rs:dbtype='str' dt:maxLength='255'/>
</s:AttributeType>
<s:AttributeType name='c5' rs:name='v.id_viag_sit' rs:number='6' rs:nullable='true' rs:write='true'>
<s:datatype dt:type='number' rs:dbtype='numeric' dt:maxLength='19' rs:scale='0' rs:precision='19' rs:fixedlength='true'/>
</s:AttributeType>
<s:AttributeType name='c6' rs:name='v.id_viag_objtv' rs:number='7' rs:nullable='true' rs:write='true'>
<s:datatype dt:type='number' rs:dbtype='numeric' dt:maxLength='19' rs:scale='0' rs:precision='19' rs:fixedlength='true'/>
</s:AttributeType>
<s:AttributeType name='c7' rs:name='v.id_viajt' rs:number='8' rs:nullable='true' rs:write='true'>
<s:datatype dt:type='number' rs:dbtype='numeric' dt:maxLength='19' rs:scale='0' rs:precision='19' rs:fixedlength='true'/>
</s:AttributeType>
<s:AttributeType name='c8' rs:name='v.nu_viag' rs:number='9' rs:nullable='true' rs:write='true'>
<s:datatype dt:type='number' rs:dbtype='numeric' dt:maxLength='19' rs:scale='0' rs:precision='9' rs:fixedlength='true'/>
</s:AttributeType>
<s:AttributeType name='c9' rs:name='v.dt_ptcol' rs:number='10' rs:nullable='true' rs:write='true'>
<s:datatype dt:type='dateTime' rs:dbtype='timestamp' dt:maxLength='16' rs:scale='6' rs:precision='26' rs:fixedlength='true'/>
</s:AttributeType>
<s:AttributeType name='c10' rs:name='v.dt_cria_viag' rs:number='11' rs:nullable='true' rs:write='true'>
<s:datatype dt:type='dateTime' rs:dbtype='timestamp' dt:maxLength='16' rs:scale='6' rs:precision='26' rs:fixedlength='true'/>
</s:AttributeType>
<s:AttributeType name='c11' rs:name='v.dt_ini_viag' rs:number='12' rs:nullable='true' rs:write='true'>
<s:datatype dt:type='dateTime' rs:dbtype='timestamp' dt:maxLength='16' rs:scale='6' rs:precision='26' rs:fixedlength='true'/>
</s:AttributeType>
<s:AttributeType name='c12' rs:name='v.dt_fim_viag' rs:number='13' rs:nullable='true' rs:write='true'>
<s:datatype dt:type='dateTime' rs:dbtype='timestamp' dt:maxLength='16' rs:scale='6' rs:precision='26' rs:fixedlength='true'/>
</s:AttributeType>
<s:AttributeType name='c13' rs:name='v.dt_canclmt' rs:number='14' rs:nullable='true' rs:write='true'>
<s:datatype dt:type='dateTime' rs:dbtype='timestamp' dt:maxLength='16' rs:scale='6' rs:precision='26' rs:fixedlength='true'/>
</s:AttributeType>
<s:AttributeType name='c14' rs:name='v.ds_dtlhmt_objtv_viag' rs:number='15' rs:nullable='true' rs:write='true'>
<s:datatype dt:type='string' rs:dbtype='str' dt:maxLength='255'/>
</s:AttributeType>
<s:AttributeType name='c15' rs:name='v.ds_justfcv_ptp' rs:number='16' rs:nullable='true' rs:write='true'>
<s:datatype dt:type='string' rs:dbtype='str' dt:maxLength='255'/>
</s:AttributeType>
<s:AttributeType name='c16' rs:name='v.in_rduc_aux_viag' rs:number='17' rs:nullable='true' rs:write='true'>
<s:datatype dt:type='string' rs:dbtype='str' dt:maxLength='255'/>
</s:AttributeType>
<s:AttributeType name='c17' rs:name='v.ds_justfcv_oa' rs:number='18' rs:nullable='true' rs:write='true'>
<s:datatype dt:type='string' rs:dbtype='str' dt:maxLength='255'/>
</s:AttributeType>
<s:AttributeType name='c18' rs:name='v.vl_oa' rs:number='19' rs:nullable='true' rs:write='true'>
<s:datatype dt:type='number' rs:dbtype='numeric' dt:maxLength='19' rs:scale='2' rs:precision='15' rs:fixedlength='true'/>
</s:AttributeType>
<s:AttributeType name='c19' rs:name='v.ds_obs_viag' rs:number='20' rs:nullable='true' rs:write='true'>
<s:datatype dt:type='string' rs:dbtype='str' dt:maxLength='255'/>
</s:AttributeType>
<s:AttributeType name='c20' rs:name='v.vl_aux_viag' rs:number='21' rs:nullable='true' rs:write='true'>
<s:datatype dt:type='number' rs:dbtype='numeric' dt:maxLength='19' rs:scale='2' rs:precision='15' rs:fixedlength='true'/>
</s:AttributeType>
<s:AttributeType name='c21' rs:name='v.sg_cod_centro_cust' rs:number='22' rs:nullable='true' rs:write='true'>
<s:datatype dt:type='string' rs:dbtype='str' dt:maxLength='255'/>
</s:AttributeType>
<s:AttributeType name='c22' rs:name='v.in_envd_dou' rs:number='23' rs:nullable='true' rs:write='true'>
<s:datatype dt:type='string' rs:dbtype='str' dt:maxLength='255'/>
</s:AttributeType>
<s:AttributeType name='c23' rs:name='v.in_aprv_viag' rs:number='24' rs:nullable='true' rs:write='true'>
<s:datatype dt:type='string' rs:dbtype='str' dt:maxLength='255'/>
</s:AttributeType>
<s:AttributeType name='c24' rs:name='v.dt_ult_export_ptp' rs:number='25' rs:nullable='true' rs:write='true'>
<s:datatype dt:type='dateTime' rs:dbtype='timestamp' dt:maxLength='16' rs:scale='6' rs:precision='26' rs:fixedlength='true'/>
</s:AttributeType>
<s:AttributeType name='c25' rs:name='v.in_pend_export_ptp' rs:number='26' rs:nullable='true' rs:write='true'>
<s:datatype dt:type='string' rs:dbtype='str' dt:maxLength='255'/>
</s:AttributeType>
<s:AttributeType name='c26' rs:name='v.sg_cod_centro_cust_aprvdr' rs:number='27' rs:nullable='true' rs:write='true'>
<s:datatype dt:type='string' rs:dbtype='str' dt:maxLength='255'/>
</s:AttributeType>
<s:AttributeType name='c27' rs:name='v.id_locc_cmptlhd' rs:number='28' rs:nullable='true' rs:write='true'>
<s:datatype dt:type='number' rs:dbtype='numeric' dt:maxLength='19' rs:scale='0' rs:precision='19' rs:fixedlength='true'/>
</s:AttributeType>
<s:AttributeType name='c28' rs:name='v.nm_org_viajt' rs:number='29' rs:nullable='true' rs:write='true'>
<s:datatype dt:type='string' rs:dbtype='str' dt:maxLength='255'/>
</s:AttributeType>
<s:extends type='rs:rowbase'/>
</s:ElementType>
</s:Schema>
<rs:data>
<z:row c0='46162' c1='2021-12-31T08:14:52.055421000' c2='UC_VIA' c3='2022-01-11T17:18:20.136658000' c4='UC_VIA'
c5='8' c6='31' c7='15528' c8='202220019' c9='2021-12-31T08:14:51.645000000' c10='2021-12-31T08:14:51.645000000'
c11='2022-01-06T00:00:00' c12='2022-01-07T00:00:00' c14='Reuniões com SPU.' c16='N' c19='OUTROS' c21='DIR5'
c22='N' c23='S' c25='N' c26='DIR5' c28='GP'/>
<z:row c0='46183' c1='2021-12-30T08:14:49.253637000' c2='UC_VIA' c3='2022-01-25T21:06:39.985815000' c4='UC_VIA'
c5='8' c6='31' c7='2435' c8='202220017' c9='2021-12-30T00:00:00' c10='2021-12-30T08:14:49.129000000' c11='2022-01-20T00:00:00'
c12='2022-01-21T00:00:00' c14='Realização da Audiência Pública da PPP Prisional de Blumenau/SC' c16='N' c21='AGOV/DEPS1'
c22='N' c23='S' c25='S' c26='AGOV/DEPS1' c28='AGOV/DEPS1'/>
</rs:data>
</xml>
I am using the following XSL file to convert this file.
XSL converter
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:rs="urn:schemas-microsoft-com:rowset"
exclude-result-prefixes="rs">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/">
<!-- root element for the XML output -->
<rootElement xmlns:z="#RowsetSchema" xsl:exclude-result-prefixes="z">
<!-- for each z:row element in the ADO output -->
<xsl:for-each select="/xml/rs:data/z:row">
<!--
This will be used for the table name imported into Access.
Change this name to suit your needs.
-->
<TableName>
<!--
for each attribute of the z:row element in the ADO XML document
-->
<xsl:for-each select="@*">
<!--
dynamically create elements and fill with attribute
value using the XPath name() function
-->
<xsl:element name="{name()}">
<xsl:value-of select="."/>
</xsl:element>
</xsl:for-each>
</TableName>
</xsl:for-each>
</rootElement>
</xsl:template>
</xsl:stylesheet>
After conversion, I import the new XML into MS Access, creating a table. The result is this: Table results image
The name()
function in line <xsl:element name="{name()}">
is returning the value of the name
attribute on the XML schema(C0, C1, C2, etc). The correct column names are in the rs:name
attribute in the schema, but after hours of work I was not able to figure out how to correctly grab the column titles.
Can anyone point me to the right direction here? How do I get the column names from the XML schema?
Thanks in advance!
CodePudding user response:
Consider searching the s:AttributeType
nodes for matching @name
to current attribute name()
, then return corresponding rs:name
. Also use translate()
to convert the dots (special character in database column names) to underscore. Note the added prefix declaration for s
in root since XPath uses it.
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:rs="urn:schemas-microsoft-com:rowset"
xmlns:s='uuid:BDC6E3F0-6DA3-11d1-A2A3-00AA00C14882'
exclude-result-prefixes="rs">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/">
<!-- root element for the XML output -->
<rootElement xmlns:z="#RowsetSchema" xsl:exclude-result-prefixes="z">
<!-- for each z:row element in the ADO output -->
<xsl:for-each select="/xml/rs:data/z:row">
<!--
This will be used for the table name imported into Access.
Change this name to suit your needs.
-->
<TableName>
<!--
for each attribute of the z:row element in the ADO XML document
-->
<xsl:for-each select="@*">
<!-- CAPTURE CURRENT ATTRIBUTE NAME -->
<xsl:variable name="curr_name" select="name()"/>
<!-- SEARCH s:AttributeType FOR MATCHING @name, RETURN @rs:name -->
<xsl:variable name="rs_name" select="//s:AttributeType[@name=$curr_name]/@rs:name"/>
<xsl:element name="{translate($rs_name, '.', '_')}">
<xsl:value-of select="."/>
</xsl:element>
</xsl:for-each>
</TableName>
</xsl:for-each>
</rootElement>
</xsl:template>
</xsl:stylesheet>
CodePudding user response:
XSLT has a built-in key mechanism for resolving cross-references. I strongly recommend you take advantage of it:
XSLT 2.0
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:s='uuid:BDC6E3F0-6DA3-11d1-A2A3-00AA00C14882'
xmlns:rs='urn:schemas-microsoft-com:rowset'
xmlns:z='#RowsetSchema'
exclude-result-prefixes="#all">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:key name="col" match="s:AttributeType" use="@name" />
<xsl:template match="/xml">
<rootElement>
<xsl:for-each select="rs:data/z:row">
<TableName>
<xsl:for-each select="@*">
<xsl:element name="{key('col', name())/@rs:name}">
<xsl:value-of select="."/>
</xsl:element>
</xsl:for-each>
</TableName>
</xsl:for-each>
</rootElement>
</xsl:template>
</xsl:stylesheet>