xml er netop skabt til at kunne transformeres til en anden form, eller hente data fra, så er det er et meget forståeligt behov du har.
Jeg kommenterer uden at kende nogen brugervenlig let løsning, for at få lejlighed til at oplyse om at det enerådende paragdigme på området er xslt transformation - hvilket understreges af mange gængse programmeringssprog (kender java, c++/c (expat, xerces) og ms-access) de sidste 10 år har haft funktioner der forholdsvis let klarer det.
Har man aldrig set sådan noget før, er det dog noget langhåret, men jeg vil illustrere med en case fra min virklighed. Bygma har netop introduceret elektroniske fakturaer og disse vil jeg dels hive data ud af og dels visse i en ms-access raport.
I første omgang må du tænke dig til en Bygma faktura - kan listes om ønskes, men den fylder meget som tekst
Transformations scriptet jeg anvender ser sådan ud:
*********** start på filen bygmaInv.xsl *****************
<xsl:stylesheet version="1.0" xmlns:xsl="
http://www.w3.org/1999/XSL/Transform" xmlns:com="
http://rep.oio.dk/ubl/xml/schemas/0p71/common/" xmlns:rotns="
http://rep.oio.dk/ubl/xml/schemas/0p71/pie/" >
<!-- exclude-result-prefixes="rs" xsl:exclude-result-prefixes="z" -->
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="no"/>
<xsl:template match="/">
<!-- root element for the XML output -->
<rootElement xsl:exclude-result-prefixes="com rotns">
<table name="Invoice">
<fields>fakNr,fakDate,buyCvr,buyN1,buyA1,buyA2,destN1,destA1,destA2,sellerCvr,sellerSE,sellerN1,sellerA1,sellerA2,orderContactId,orderContactName,orderContactTel,paymTypeId,paymDate,paymId,payJId,vatPct,taxAA,taxA,curId</fields>
<rec>'<xsl:apply-templates select="/rotns:Invoice/com:ID" />','<xsl:apply-templates select="/rotns:Invoice/com:IssueDate" />',<xsl:apply-templates select="/rotns:Invoice/com:BuyerParty" /><xsl:apply-templates select="/rotns:Invoice/com:DestinationParty" /><xsl:apply-templates select="/rotns:Invoice/com:SellerParty" /><xsl:apply-templates select="/rotns:Invoice/com:PaymentMeans" /><xsl:apply-templates select="/rotns:Invoice/com:TaxTotal/com:CategoryTotal" /></rec>
</table>


<table name="InvLine">
<fields>unit,case,buyer,quan,amount,redPcnt,descp</fields>
<xsl:for-each select="/rotns:Invoice/com:InvoiceLine" >
<xsl:choose>
<xsl:when test="com:LineExtensionAmount!=0">
<rec>'<xsl:value-of select="com:InvoicedQuantity/@unitCode" />','<xsl:value-of select="com:ReferencedOrderLine/com:SellersID" />','<xsl:value-of select="com:ReferencedOrderLine/com:BuyersID" />',<xsl:value-of select="com:InvoicedQuantity" />,<xsl:value-of select="com:LineExtensionAmount" />,<xsl:choose><xsl:when test="com:ReferencedOrderLine/com:AllowanceCharge/com:MultiplierFactorQuantity" ><xsl:value-of select="com:ReferencedOrderLine/com:AllowanceCharge/com:MultiplierFactorQuantity" />,'</xsl:when><xsl:otherwise>0,'</xsl:otherwise></xsl:choose><xsl:value-of select="com:Item/com:Description" />'</rec></xsl:when></xsl:choose></xsl:for-each ></table>
</rootElement>
</xsl:template>
<xsl:template match="com:BuyerParty">'<xsl:apply-templates select="com:ID" />','<xsl:apply-templates select="com:PartyName/com:Name" />',<xsl:apply-templates select="com:Address" /></xsl:template>
<xsl:template match="com:DestinationParty">'<xsl:apply-templates select="com:PartyName/com:Name" />',<xsl:apply-templates select="com:Address" /></xsl:template>
<xsl:template match="com:SellerParty">'<xsl:apply-templates select="com:ID" />','<xsl:apply-templates select="com:PartyTaxScheme/com:CompanyTaxID" />','<xsl:apply-templates select="com:PartyName/com:Name" />',<xsl:apply-templates select="com:Address" /><xsl:apply-templates select="com:OrderContact" /></xsl:template>
<xsl:template match="com:Address">'<xsl:apply-templates select="com:Street" />','<xsl:apply-templates select="com:PostalZone" /><xsl:text> </xsl:text><xsl:apply-templates select="com:CityName" />',</xsl:template>
<xsl:template match="com:OrderContact">'<xsl:apply-templates select="com:ID" />','<xsl:apply-templates select="com:Name" />','<xsl:apply-templates select="com:Phone" />',</xsl:template>
<xsl:template match="com:PaymentMeans">'<xsl:apply-templates select="com:TypeCodeID" />','<xsl:apply-templates select="com:PaymentDueDate" />','<xsl:apply-templates select="com:PaymentID" />','<xsl:apply-templates select="com:JointPaymentID" />',</xsl:template>
<xsl:template match="com:CategoryTotal"><xsl:apply-templates select="com:RatePercentNumeric" />,<xsl:apply-templates select="com:TaxAmounts/com:TaxableAmount" />,<xsl:apply-templates select="com:TaxAmounts/com:TaxAmount" />,'<xsl:apply-templates select="com:TaxAmounts/com:TaxAmount/@currencyID" />'</xsl:template>
<xsl:template match="*"><xsl:value-of select="." /></xsl:template>
</xsl:stylesheet>
********* slut på filen bygmaInv.xsl ***************
Hvad eller ;)
Denne fil anvendes i dette eksempel:
Sub testtransformXmlToTabel()
transformXmlToTabels C:\home\dev\access\40_6479417_bygma.xml",C:\var\access\bygmaInv.xsl
End Sub
Og her er den vba programstump som putter fakturaen i tabellerne Invoice og InvLine. Det siger lidt om hvor stærk xlst i sin generalitet er, at alt arbejdet i følgende subrutine sker i de 3 programlinier som følger 'for each' statements
Sub transformXmlToTabels(xmlIn, xslt)
Dim domIn As DOMDocument30, domStylesheet As DOMDocument30, domOut As DOMDocument30
Dim tblDescNode As IXMLDOMElement, rec As IXMLDOMElement
Dim tblName, fldList
Set domIn = New DOMDocument30
domIn.async = False
sqlE.Delete tbl.InvLine
sqlE.Delete tbl.Invoice
If domIn.Load(xmlIn) Then
Set domStylesheet = New DOMDocument30
domStylesheet.Load xslt
If Not domStylesheet Is Nothing Then
Set domOut = New DOMDocument30
domIn.transformNodeToObject domStylesheet, domOut
For Each tblDescNode In domOut.documentElement.getElementsByTagName("table")
tblName = tblDescNode.Attributes.getNamedItem("name").nodeValue
fldList = tblDescNode.getElementsByTagName("fields").item(0).text
For Each rec In tblDescNode.getElementsByTagName("rec")
sqlE.insert tblName, "(" & fldList & ")", rec.text
'Debug.Print "insert into " & tblName & "(" & fldList & ") values(" & rec.text & ")"
Next: Next: End If: End If
Set domIn = Nothing
Set domOut = Nothing
Set domStylesheet = Nothing
End Sub