I am trying an example DBF -> XML from xHarbour Guide
/*part of code
.....
IF aField[2] == "M"
// Memo fields are written as CDATA
cData := FieldGet( Hb_EnumIndex() )
oXmlField := TXmlNode():new( HBXML_TYPE_CDATA , ;
Lower( aField[1] ), ;
NIL , ;
cData )
*/
=== conversion result
<?xml version="1.0" encoding="windows-1251" ?>
- <database name="XMEMO">
- <structure>
<field dec="0" len="10" name="w1m" type="M" />
</structure>
- <records>
- <record id="1">
- <![CDATA[ 1 ]]>
</record>
- <record id="2">
- <![CDATA[ 2 ]]>
</record>
</records>
</database>
====
I think the result of conversion memo-field is incorrect,
result should contain the name of the field
- <record id="2">
<w1m>
- <![CDATA[ 2 ]]>
<\w1m>
</record>
--
Regards, Anatole.
Best regards, Anatole
Anatole Kolotovkin пишет:
Why do you think the field name needs to be repeated for every record,
when it is not for any other variable type?
> - <structure>
> <field dec="0" len="10" name="w1m" type="M" />
> </structure>
... I see a "w1m" clearly in what you reported as output. What do you
get for a regular character field?
David A. Smith
Anatole,
You are welcome to try this function, it works for me. Use it as a
starting point for your own work.
#include "hbXml.ch"
****************************************
FUNCTION DBF2XML( cDataName, cOutName )
*
* Purpose: convert an xBase file to XML
* returns the number of records converted
*
LOCAL aStruct, aField, nFileHandle, nK := 0
LOCAL oXmlDoc, oXmlNode, hAttr, cData
LOCAL OXmlDatabase, oXmlStruct, oXmlRecord, oXmlField
USE (cDataName)
aStruct := DbStruct()
*- Create empty XML document with header
oXmlDoc := TXmlDocument():new( '<?xml version="1.0"?>' )
*- Create main XML node
oXmlDatabase := TXmlNode():new( , "database", { "name" =>
GetFileName(cDataName) } )
oXmlDoc:oRoot:addBelow( oXmlDatabase )
*- copy structure information to XML
oXmlStruct := TXmlNode():new( , "structure" )
oXmlDataBase:addBelow( oXmlStruct )
FOR EACH aField IN aStruct
*- store field information in XML attributes
hAttr := { "name" => Lower( aField[1] ), ;
"type" => aField[2], ;
"len" => LTrim( Str(aField[3]) ), ;
"dec" => LTrim( Str(aField[4]) ) }
oXmlField := TXmlNode():new(, "field", hAttr )
oXmlStruct:addBelow( oXmlField )
NEXT
*- copy all records to XML
oXmlNode := TXmlNode():new( , "records" )
oXmlDataBase:addBelow( oXmlNode )
BEGIN SEQUENCE
DO WHILE !EOF() .and. RECNO() < 101
hAttr := { "id" => LTrim( Str( Recno() ) ) }
oXmlRecord := TXmlNode():new( , "record", hAttr )
FOR EACH aField IN aStruct
IF aField[2] == "M"
*- Memo fields are written as CDATA
cData := FieldGet( Hb_EnumIndex() )
oXmlField := TXmlNode():new( HBXML_TYPE_CDATA , ;
Lower( aField[1] ), ;
NIL , ;
cData )
ELSE
*- other fields are written as normal tags
cData := FieldGet( Hb_EnumIndex() )
cData := Alltrim( CStr( cData ) )
oXmlField := TXmlNode():new( HBXML_TYPE_TAG , ;
Lower( aField[1] ), ;
NIL , ;
cData )
ENDIF
*- add field node to record
oXmlRecord:addBelow( oXmlField )
NEXT
*- add record node to records
oXmlNode:addBelow( oXmlRecord )
SKIP
ENDDO
*- create XML file
nFileHandle := FCreate( cOutName )
*- write the XML tree, this takes a long time.
oXmlDoc:write( nFileHandle, HBXML_STYLE_INDENT )
*- close files
FClose( nFileHandle )
END // SEQUENCE
CLOSE (cDataname)
RETURN( nK )
*
Good Luck,
-- Robert
Thank you for your response. Example of xHarbour Guide gives the
following result for a regular character field AND for memo field
<?xml version="1.0"?>
<database name="X2MEMO">
<structure>
<field dec="0" len="3" name="w1" type="C"/>
<field dec="0" len="3" name="w2" type="C"/>
<field dec="0" len="10" name="w2m" type="M"/>
<field dec="0" len="10" name="w3m" type="M"/>
<field dec="0" len="3" name="w3" type="N"/>
</structure>
<records>
<record id="1">
<w1>001</w1>
<w2>100</w2>
<![CDATA[001 ]]>
<![CDATA[100 ]]>
<w3>1</w3>
</record>
--
Regards, Anatole.
Thank you for your reply.
Your function gives a result similar to my
<?xml version="1.0"?>
<database name="X2MEMO">
<structure>
<field dec="0" len="3" name="w1" type="C"/>
<field dec="0" len="3" name="w2" type="C"/>
<field dec="0" len="10" name="w2m" type="M"/>
<field dec="0" len="10" name="w3m" type="M"/>
<field dec="0" len="3" name="w3" type="N"/>
</structure>
<records>
<record id="1">
<w1>001</w1>
<w2>100</w2>
<![CDATA[001 ]]>
<![CDATA[100 ]]>
<w3>1</w3>
</record>
.........
Remaining questions
1. xml2dbf How to find the field w2m or field w3m
2. from W3C Recommendation.
================================
2.7 CDATA Sections
[Definition: CDATA sections may occur anywhere character data may occur;
they are used to escape blocks of text containing characters which would
otherwise be recognized as markup. CDATA sections begin with the string
"<![CDATA[" and end with the string "]]>":]
=============================================================
IHMO, for memo-field must
<w2m>>
<![CDATA[001 ]]>
</w2m>
3. example XML from HWGUI
=======
- <method name="onFormInit">
- <![CDATA[
oForm1 := HFormTmpl():Read( "testget1.xml" )
oForm2 := HFormTmpl():Read( "testget2.xml" )
oForm3 := HFormTmpl():Read( "testdbf1.xml" )
oForm4 := HFormTmpl():Read( "test_ctrl.xml" )
oForm5 := HFormTmpl():Read( "barcode.xml" )
orep1 := hreptmpl():Read("testrep1.xml")
]]>
</method>
--
Regards, Anatole.
I suggest you reading document <xHb>/doc/hbxml.txt for begining ...
There you can see:
"
HBXML_TYPE_DATA
A pure data node. In this node-type only ::cData is valid, as all
other elements are meaningless.
"
and then you will correct code to work like you like.
Anatole Kolotovkin wrote in post <hf41cj$7ec$1...@news.eternal-september.org> ...
[...]
> >> IF aField[2] == "M"
> >> // Memo fields are written as CDATA
> >> cData := FieldGet( Hb_EnumIndex() )
> >> oXmlField := TXmlNode():new( HBXML_TYPE_CDATA , ;
> >> Lower( aField[1] ), ;
> >> NIL , ;
> >> cData )
[...]
Change to:
xData := FieldGet( Hb_EnumIndex() )
IF aField[ DBS_TYPE ] == "M"
// Memo field as CDATA
oN_field := TXmlNode():new( HBXML_TYPE_TAG, ;
Lower( aField[ DBS_NAME ] ) )
oCData := TXmlNode():new( HBXML_TYPE_CDATA, ;
,, RTrim( xData ) )
oN_field:addBelow( oCData )
ELSE
...
With best regards,
Dusan
Well, Anatole, you got me there because in my limited exposure to
XML I do not need to export or import any "Memo" fields. I do
remember though, the trouble I had when I was first trying to
teach myself about XML that the Memo fields were a problem. This
code is how I solved the problem -- temporarily, but I do not use
Memo fields in production.
-- Robert
> Well, Anatole, you got me there because in my limited exposure to XML I
> do not need to export or import any "Memo" fields. I do remember though,
> the trouble I had when I was first trying to teach myself about XML that
> the Memo fields were a problem. This code is how I solved the problem --
> temporarily, but I do not use Memo fields in production.
>
> -- Robert
I understand, thank you.
--
Regards, Anatole.
I now understand, TXmlNode():new( HBXML_TYPE_CDATA,"xName",NIL,cData)
gives no false positives, but only one result, which is valid in XML
IMHO, it would be good
if empty(cName)
<![CDATA ......>
else
<cName>
<![CDATA ......>
</cName>
Regards, Anatole.