Skip to content

Instantly share code, notes, and snippets.

@elutz
Last active December 17, 2021 14:33
Show Gist options
  • Save elutz/d4a6fdab8c1f77f2fb4ec392dcc632c6 to your computer and use it in GitHub Desktop.
Save elutz/d4a6fdab8c1f77f2fb4ec392dcc632c6 to your computer and use it in GitHub Desktop.
4D: XML to Object, main method is "Allg_XML_toObject"
// Method: Allg_XML_ParseElement
// Parameters:
// Description
// Parsen eines XML-Elements
// wird rekursiv aufgerufen
// siehe auch Allg_XML_toObject
C_TEXT($1; $xmlRef) // XML-Referenz auf den Wurzelknoten
C_OBJECT($2; $obj) // Return, Object wenn Element, enthält alle Elemente des Wurzelknotens, nicht den Wurzelknoten selbst
C_TEXT($0; $retText) // Return: text, wenn Textknoten
$xmlRef:=$1
$obj:=$2
$retText:=""
C_OBJECT($retobj)
// Child nodes holen
ARRAY LONGINT($types; 0)
ARRAY TEXT($values; 0)
DOM GET XML CHILD NODES($xmlRef; $types; $values)
ARRAY TEXT($elementNames; Size of array($values))
ARRAY TEXT($enumArray; 0)
// über Child nodes iterieren
C_LONGINT($i)
For ($i; 1; Size of array($types))
Case of
: ($types{$i}=XML DATA)
$retText:=Allg_String_Trim($values{$i})
: ($types{$i}=XML ELEMENT)
$retobj:=New object
C_TEXT($elname)
DOM GET XML ELEMENT NAME($values{$i}; $elname)
$elname:=Lowercase($elname) // IBPP-2606: Objekt-Attributnamen einheitlich machen!
// Behandlung von Aufzählungen als Array
// Zuerst feststellen, ob sich Tagname wiederholt
C_LONGINT($alreadyExistsAt)
C_BOOLEAN($isEnum)
$alreadyExistsAt:=Find in array($elementNames; $elname)
$isEnum:=($alreadyExistsAt>0)
$elementNames{$i}:=$elname
C_TEXT($text)
$text:=Allg_XML_ParseElement($values{$i}; $retobj) // IBPP-2606: ignore uppercase in XML tags!
Case of
: ($isEnum) // Umwandlung einer Aufzählung in ein Array
C_COLLECTION($coll)
Case of
: (OB Get type($obj; $elname)=Is collection)
// Collection existiert bereits
: (OB Get type($obj; $elname)=Is undefined)
$coll:=New collection
$obj[$elname]:=$coll
Else
// was anderes
// vorherigen Wert holen
$coll:=New collection
//und in Collection packen
$coll.push($obj[$elname])
$obj[$elname]:=$coll
End case
If (Length($text)>0)
C_LONGINT($num)
$num:=Num($text)
// Testen ob Wert eine Zahl sein könnte
If (String($num)=$text)
// ist Zahl
// JSON wird als {"key": 2} gerendert
$obj[$elname].push($num)
Else
// ist Text
// JSON wird als {"key": "2text"} gerendert
$obj[$elname].push($text)
End if
Else
$obj[$elname].push($retobj)
End if
: (Length($text)>0) // Im Falle eines Textknotens
C_LONGINT($num)
$num:=Num($text)
// Testen ob Wert eine Zahl sein könnte
If (String($num)=$text)
// ist Zahl
// JSON wird als {"key": 2} gerendert
OB SET($obj; $elname; $num)
Else
// ist Text
// JSON wird als {"key": "2text"} gerendert
OB SET($obj; $elname; $text)
End if
: (Not(OB Is empty($retobj))) // Objektknoten
OB SET($obj; $elname; $retobj)
Else
// nüscht
End case
: ($types{$i}=XML CDATA)
$retText:=Allg_String_Trim($values{$i})
: ($types{$i}=XML comment)
// NOOP
Else
Allg_LogText(Current method name+" else "+$values{$i}+" type="+String($types{$i}))
End case
End for
$0:=$retText
// Method: Allg_XML_toObject
// Description
// Wandelt eine gegebene XML-Hierarchie in ein entsprechend
// hierarchisches Object um.
// Einschränkungen:
// 1. Es werden nur XML-Elemente-Werte berücksichtigt, XML-Attributwerte
// werden derzeit nicht ausgelesen.
// 2. Es werden nur streng hierarchische Strukturen unterstützt, dies z.B.
// wird nicht korrekt behandelt:
// <myElement>Hallo<br/>New<br/>York</myElement>
// Hier eine korrekte Struktur:
// <myElement>
// <el1>Hallo</el1>
// <el2>New</el2>
// <el3>York</el3>
// </myElement>
// wird zu: { "myElement": {
// "el1": "Hallo",
// "el2": "New",
// "el3": "York"
// } }
// 3. Es werden nun auch wiederholenden Elemente in einer Hierarchiestufe
// unterstützt.
// Das geht z.B. jetzt:
// <profile>
// <Tab>
// <heading>Persönliche Daten</heading>
// <template>personal</template>
// </Tab>
// <Tab>
// <heading>Beobachtete Vorhaben</heading>
// <template>observed</template>
// </Tab>
//</profile>
//
// Parameters
// ----------------------------------------------------
C_TEXT($1; $xmlRef) // XML-Referenz auf den Wurzelknoten, ab dem das Objekt gebaut wird
C_OBJECT($0; $obj) // // Return: das gebaute Objekt
$xmlRef:=$1
$obj:=New object
C_TEXT($rootname)
DOM GET XML ELEMENT NAME($xmlRef; $rootname)
Allg_XML_ParseElement($xmlRef; $obj)
// Wurzelbehandlung
C_OBJECT($newobj)
OB SET($newobj; $rootname; $obj)
$0:=$newobj
@elutz
Copy link
Author

elutz commented Dec 17, 2021

Note: Start with Allg_XML_toObject

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment