#define NL (CHR(13)+CHR(10)) m.lcInput = [<?xml version="1.0" encoding="iso-8859-1" ?>] + NL +; [<my-songs>] + NL +; [<song>] + NL +; [<song-title song.lang="fr">La valse à mille temps</song-title>] + NL +; [<singer nat="be">Jacques Brel</singer>] + NL +; [</song>] + NL +; [<song>] + NL +; [<song-title song.lang="en">If walls could talk</song-title>] + NL +; [<singer nat="ca">Céline Dion</singer>] + NL +; [</song>] + NL +; [</my-songs>] + NL LOCAL xpto as MSXML2.DOMDocument30, xyz as MSXML2.DOMDocument30 m.xpto = CREATEOBJECT("MSXML2.DOMDocument.3.0") m.xpto.async = .F. m.xpto.loadXML(m.lcInput) m.xyz = CREATEOBJECT("MSXML2.DOMDocument.3.0") m.xyz.async = .F. m.xyz.loadXML(ReEncodeXML("iso-8859-1",m.xpto)) clear ? m.xyz.xml * * ReEncodeXML * * Rebuild a XML document assuring a specific character encoding * * Parameters: * tcTargetEncoding - such as "utf-8" or "iso-8859-1" * tvDocument - XML document in string or object form * Returns: * a XML string under the specified encoding FUNCTION ReEncodeXML (tcTargetEncoding AS String, tvDocument AS Object) LOCAL lcReencoder AS String LOCAL loXML AS MSXML2.DOMDocument30 LOCAL loStyleSheet AS MSXML2.DOMDocument30 LOCAL loResult AS MSXML2.DOMDocument30 LOCAL lcResultFile AS String LOCAL lcResultXML AS String * compose the reencoder stylesheet * it's just a simple stylesheet to copy the entire document under the specified encoding * - ok, that was the original comment: now, what this particular stylesheet does is to * traverse all XML tree, looking for attribute and elements with names with . and - in * them and change them to _ so that XMLTOCURSOR can read them properly m.lcReencoder = [<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">] + NL +; [<xsl:output method="xml" ] +; [encoding="] + LOWER(ALLTRIM(m.tcTargetEncoding)) + [" ] +; [omit-xml-declaration="no" indent="yes"/> ] + NL +; [<xsl:template match="@*">] + NL +; [<xsl:choose>] + NL +; [<xsl:when test="contains(name(),'-') or contains(name(),'.')">] + NL +; [<xsl:attribute name="{translate(name(),'-.','__')}">] + NL +; [<xsl:value-of select="." />] + NL +; [</xsl:attribute>] + NL +; [</xsl:when>] + NL +; [<xsl:otherwise>] + NL +; [<xsl:copy />] + NL +; [</xsl:otherwise>] + NL +; [</xsl:choose>] + NL +; [</xsl:template>] + NL +; [<xsl:template match="/ | node()">] + NL +; [<xsl:choose>] + NL +; [<xsl:when test="contains(name(),'-') or contains(name(),'.')">] + NL +; [<xsl:element name="{translate(name(),'-.','__')}">] + NL +; [<xsl:apply-templates select="@* | node()"/>] + NL +; [</xsl:element>] + NL +; [</xsl:when>] + NL +; [<xsl:otherwise>] + NL +; [<xsl:copy>] + NL +; [<xsl:apply-templates select="@* | node()"/>] + NL +; [</xsl:copy>] + NL +; [</xsl:otherwise>] + NL +; [</xsl:choose>] + NL +; [</xsl:template>] + NL +; [</xsl:stylesheet>] + NL * create an XML object from the string or uses the supplied one as parameter IF TYPE("m.tvDocument")="C" m.loXML = CREATEOBJECT("MSXML2.DOMDocument.3.0") m.loXML.async = .F. m.loXML.loadXML(m.tvDocument) ELSE m.loXML = m.tvDocument ENDIF * create an XML object for the stylesheet m.loStyleSheet = CREATEOBJECT("MSXML2.DOMDocument.3.0") m.loStyleSheet.async = .F. m.loStyleSheet.loadXML(m.lcReencoder) * create the reencoded object m.loResultXML = CREATEOBJECT("MSXML2.DOMDocument.3.0") m.loResultXML.async = .F. m.loResultXML.validateOnParse = .T. * execute the transformation and store the transformation in the new object m.loXML.transformNodeToObject(m.loStyleSheet,m.loResultXML) * save the result to a temporary file and read it back as a string m.lcResultFile = ADDBS(SYS(2023))+SYS(2015)+".xml" m.loResultXML.save(m.lcResultFile) m.lcResultXML = FILETOSTR(m.lcResultFile) ERASE (m.lcResultFile) * return it RETURN m.lcResultXML ENDFUNC