{"id":832,"date":"2013-01-10T14:41:02","date_gmt":"2013-01-10T13:41:02","guid":{"rendered":"http:\/\/www.capri-soft.de\/blog\/?p=832"},"modified":"2018-06-12T20:42:33","modified_gmt":"2018-06-12T18:42:33","slug":"ibm-doors-dxl-die-fehlenden-stringfunktionen-the-missing-string-functions","status":"publish","type":"post","link":"https:\/\/www.capri-soft.de\/blog\/?p=832","title":{"rendered":"IBM Doors DXL: Die fehlenden Stringfunktionen \/ The missing String functions"},"content":{"rendered":"<h1>Problem<\/h1>\n<p>DXL besitzt leider nur sehr wenige Stringfunktionen. Man muss sich f\u00fcr einfache Stringmanipulationen eine eigene Bibliothek bauen.<br \/>\nDXL consists only of a very less number of string functions. For this purpose you have to implement your own library.<\/p>\n<h1>Ansatz &#8211; Approach<\/h1>\n<p>Ich habe die wichtigsten Stringfunktionen aus JAVA\/PHP in eine Bibliothek ausgelagert, die ich im Kopf meiner DXL Skripte einbinde&#8230;<br \/>\nI have implemented a library with the most important string function from JAVA\/PHP, which can be included in the head of DXL scripts&#8230;<\/p>\n<h1>L\u00f6sung &#8211; Solution<\/h1>\n<p>Das Einbinden erfolgt z.B. mit<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">#include &quot;\\\\\\\\der\\\\netzwerk\\\\pfad\\\\strings.inc&quot;;<\/pre>\n<p>wobei oben ein Netzwerkpfad genutzt wird. Ohne Pfadangebe muss die Datei direkt im dxl-Verzeichnis der Installation des Doors-Clients liegen.<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n\r\n\/******************************\r\n * String funktionen\r\n * @Author: Bjoern Karpenstein \r\n * @Datum:  2012-11-06 \r\n ******************************\/\r\n\/\/ Zweistellige Ganzzahl mit fuehrender Null\r\nstring getZeroPrefixedInt(int i)\r\n{\r\n\tstring s = i &quot;&quot;;\r\n\tif (i &lt; 10) s = &quot;0&quot; s &quot;&quot;;\r\n\treturn s;\r\n}\r\n \r\n\/\/ Gib datum und Uhrzeit als String\r\nstring getDateTime()\r\n{\r\n\tstring dateTimeString = &quot;&quot;;\r\n\tint now = intOf(dateAndTime(today));\r\n\tDate d = dateOnly(today);\r\n\tint day = intOf(date(stringOf(d)));\r\n\tint diff = now-day;\r\n\tint hours = diff \/ 3600;\r\n\tint mins = (diff - (3600 * hours)) \/ 60;\r\n\tint secs = diff - (hours * 3600) - (mins * 60);\r\n\r\n\treturn &quot;&lt;td&gt;&quot; stringOf(today, &quot;yyyy-MM-dd&quot;) &quot;&lt;\/td&gt;&lt;td&gt;&quot; getZeroPrefixedInt(hours) &quot;:&quot; getZeroPrefixedInt(mins) &quot;:&quot; getZeroPrefixedInt(secs) &quot;&lt;\/td&gt;&quot;;\r\n} \r\n\r\n\/\/ Gib datum und Uhrzeit als String f\u00fcr Dateien\r\nstring getFileTimestamp()\r\n{\r\n\tstring dateTimeString = &quot;&quot;;\r\n\tint now = intOf(dateAndTime(today));\r\n\tDate d = dateOnly(today);\r\n\tint day = intOf(date(stringOf(d)));\r\n\tint diff = now-day;\r\n\tint hours = diff \/ 3600;\r\n\tint mins = (diff - (3600 * hours)) \/ 60;\r\n\tint secs = diff - (hours * 3600) - (mins * 60);\r\n\r\n\treturn stringOf(today, &quot;yyyy-MM-dd&quot;) &quot;_&quot; getZeroPrefixedInt(hours) &quot;_&quot; getZeroPrefixedInt(mins) &quot;_&quot; getZeroPrefixedInt(secs) &quot;&quot;;\r\n} \r\n\r\n\/\/ Gib datum und Uhrzeit als String f\u00fcr Dateien\r\nstring getAvitumTimestamp()\r\n{\r\n\tstring dateTimeString = &quot;&quot;;\r\n\tint now = intOf(dateAndTime(today));\r\n\tDate d = dateOnly(today);\r\n\tint day = intOf(date(stringOf(d)));\r\n\tint diff = now-day;\r\n\tint hours = diff \/ 3600;\r\n\tint mins = (diff - (3600 * hours)) \/ 60;\r\n\tint secs = diff - (hours * 3600) - (mins * 60);\r\n\r\n\treturn stringOf(today, &quot;yyyy-MM-dd&quot;) &quot; &quot; getZeroPrefixedInt(hours) &quot;:&quot; getZeroPrefixedInt(mins) &quot;:&quot; getZeroPrefixedInt(secs) &quot;&quot;;\r\n} \r\n\r\n\/\/ Gib datum und Uhrzeit als String f\u00fcr Dateien\r\nstring getAvitumDate(Date d)\r\n{\r\n\treturn stringOf(d, &quot;yyyy-MM-dd&quot;);\r\n} \r\n \r\n\/\/ Gibt die Groesse eines Arrays zur\u00fcck\r\nint getArraySize(Array a){\r\n    int size = 0;\r\n    while( !null(get(a, size, 0) ) )\r\n        size++;\r\n    return size;\r\n}\r\n\r\n\/\/ Fuegt einen String in ein Array hinzu\r\nvoid addArrayString(Array a, string str)\r\n{\r\n    int array_index = getArraySize(a);\r\n\r\n    put(a, str, array_index, 0);\r\n}\r\n\r\n\/\/ Gibt den String im Array zurueck\r\nstring getArrayString(Array a, int index)\r\n{\r\n    return (string get(a, index, 0));\r\n}\r\n\r\n\/\/ Setze String f\u00fcr vorhandene Array-Position\r\nvoid setArrayString(Array a, int change_index, string newString)\r\n{\r\n\tput(a, newString, change_index, 0);\r\n}\r\n\r\n\/\/ Der notorische Sortieralgorithmus f\u00fcr Arme\r\nvoid bubbleSort(Array a, bool asc)\r\n{\r\n\tint size=getArraySize(a);\r\n\r\n\tint i=0;\r\n\tint j=0;\r\n\tfor(i=0; i&lt;size; i++)\r\n\t{\r\n\t\tfor(j=0;j&lt;size; j++)\r\n\t\t{\r\n\t\t\tbool sortierKriterium=asc?getArrayString(a,i)&lt;getArrayString(a,j):getArrayString(a,i)&gt;getArrayString(a,j);\r\n\t\t\tif(sortierKriterium)\r\n\t\t\t{\r\n\t\t\t\t\/\/ Tauschen\r\n\t\t\t\tstring swapRAM=getArrayString(a,j);\r\n\t\t\t\tsetArrayString(a, j, getArrayString(a,i));\r\n\t\t\t\tsetArrayString(a, i, swapRAM);\r\n\t\t\t\t\r\n\t\t\t}\r\n\t\t}\r\n\t}\t\r\n}\r\n\r\n\r\n\/\/ Zum analysieren eines Strings auf seine Ascii Zeichen\r\nstring giveMeAscii(string withoutAscii)\r\n{\r\n\tstring myAsciiString = &quot;&quot;;\r\n\tfor (i=0; i&lt;length(withoutAscii); i++)\r\n\t{  \r\n   \t\tchar c = withoutAscii&#x5B;i];            \/\/ &lt;&lt;&lt;--- here you go, get the char\r\n   \t\tint ascii = intOf(c);        \/\/ &lt;&lt;&lt;--- convert char to Ascii Code\r\n   \t\tmyAsciiString = myAsciiString &quot;&quot; c &quot;&#x5B;&quot; ascii &quot;]&quot;;\r\n\t}\r\n\t\r\n\treturn myAsciiString;\r\n}\r\n\r\n\/\/ Erstellt z.B. einen CSV String \r\nstring joinString(string joiner, Array str_array)\r\n{\r\n    Buffer joined = create;\r\n    int array_index = 0;\r\n\r\n    joined += &quot;&quot;;\r\n\r\n    for(array_index = 0; array_index &lt; getArraySize(str_array); array_index++)\r\n    {\r\n        joined += getArrayString(str_array, array_index);\r\n        if( array_index + 1 &lt; getArraySize(str_array) )\r\n            joined += joiner;\r\n    }\r\n\r\n    return stringOf(joined)\r\n}\r\n\r\n\/\/ Zerhackt einen String nach einem definierten Zeichen und gibt ihn als Array zurueck\r\nArray split(string splitter, string str)\r\n{\r\n    Array tokens = create(1, 1);\r\n    Buffer buf = create;\r\n    int str_index;\r\n\r\n    buf = &quot;&quot;;\r\n\r\n    for(str_index = 0; str_index &lt; length(str); str_index++){\r\n        if( str&#x5B;str_index:str_index] == splitter ){\r\n            addArrayString(tokens, stringOf(buf));\r\n            buf = &quot;&quot;;\r\n        }else{\r\n            buf += str&#x5B;str_index:str_index];\r\n        }\r\n    }\r\n    addArrayString(tokens, stringOf(buf));\r\n\r\n    delete buf;\r\n    return tokens;\r\n}\r\n\r\n\/\/ If the string starts with another string\r\nbool startsWith(string theString, string startsWithWhat)\r\n{\r\n\tif(length(theString)&lt;length(startsWithWhat))\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\treturn theString&#x5B;0:length(startsWithWhat)-1]==startsWithWhat\r\n}\r\n\r\n\/\/ Zaehlt wie oft Skip-Listen-Keys mit einem Teilstring anfangen\r\nint countKeysThatStartWith(string prefixPfad, Skip skipListeToLookForStart)\r\n{\r\n\tint countedKeys=0;\r\n\tfor myIterator in skipListeToLookForStart do \r\n  \t{\r\n    \tstring keyValue = (string key(skipListeToLookForStart));\r\n    \t\r\n    \tstring currentPfad = &quot;&quot;;\r\n    \tif(find(skipListeToLookForStart, keyValue, currentPfad))\r\n    \t{\r\n\t    \tif(startsWith( keyValue, prefixPfad))\r\n\t    \t{\r\n\t\t    \t\tcountedKeys++;\r\n\t    \t}\r\n  \t\t}\r\n  \t}\r\n  \t\r\n  \treturn countedKeys;\r\n}\r\n\r\n\/\/ A String Replace function because there is nothing in the standard\r\nstring replace (string sSource, string sSearch, string sReplace) \r\n{\r\n    int iLen = length sSource\r\n    if (iLen == 0) return &quot;&quot;\r\n    \r\n    int iLenSearch = length(sSearch)\r\n    \r\n    if (iLenSearch == 0) \r\n    { \r\n        print &quot;Parameter error&quot;, &quot;in strings.inc\/replace: search string must not be empty&quot;\r\n        return &quot;&quot; \r\n    }\r\n    \r\n    \/\/ read the first char for latter comparison -&gt; speed optimization\r\n    char firstChar = sSearch&#x5B;0]\r\n    \r\n    Buffer s = create() \r\n    int pos = 0, d1,d2;    \r\n    int i\r\n    \r\n    while (pos &lt; iLen) { \r\n        char ch = sSource&#x5B;pos]; \r\n        bool found = true\r\n        \r\n        if (ch != firstChar) {pos ++; s+= ch; continue}\r\n        for (i = 1; i &lt; iLenSearch; i++) \r\n           if (sSource&#x5B;pos+i] != sSearch&#x5B;i]) { found = false; break }\r\n        if (!found) {pos++; s+= ch; continue}\r\n        s += sReplace\r\n        pos += iLenSearch\r\n    }\r\n    \r\n    string result = stringOf s\r\n    delete s\r\n    return result\r\n}\r\n\r\n\/\/ Backslashes maskieren und LF durch &lt;br&gt; ersetzen\r\nstring mask(string toMask)\r\n{\r\n\tstring backslashStrip   = replace(toMask, &quot;\\\\&quot;, &quot;\\\\\\\\&quot;);\r\n\tstring doubleQuoteStrip = replace(backslashStrip, &quot;\\&quot;&quot;, &quot;\\\\\\&quot;&quot;);\r\n\tstring replaceLFWithBRs = replace(doubleQuoteStrip,&quot;\\n&quot;,&quot;&lt;br\/&gt;&quot;);\t\t\r\n\t\/\/ string replaceLFWithBRs = replace(doubleQuoteStrip,&quot;&#92;&#48;12&quot;,&quot;&lt;br\/&gt;&quot;);\t\t\r\n\t\/\/return replace(replaceLFWithBRs, &quot;&#92;&#48;15&quot;, &quot;&quot;);\r\n\treturn replaceLFWithBRs;\r\n}\r\n\r\n\/\/ Backslashes maskieren und LF durch &lt;br&gt; ersetzen\r\nstring unmask(string toUnMask)\r\n{\r\n\tstring backslashStrip = replace(toUnMask, &quot;\\\\\\\\&quot;,&quot;\\\\&quot;);\r\n\tstring doubleQuoteStrip = replace(backslashStrip, &quot;\\\\\\&quot;&quot;,&quot;\\&quot;&quot;);\r\n\t\r\n\t\/\/ wenn da &lt;br\/&gt; drinne sind ignoriere 13 oder 10 \r\n\t\r\n\tstring machLFWeg = replace(doubleQuoteStrip,&quot;&lt;br\/&gt;&quot;,&quot;\\n&quot;);\r\n\t\r\n\t\/\/ string machLFWeg = replace(doubleQuoteStrip,&quot;&lt;br\/&gt;&quot;,&quot;&#92;&#48;12&quot;) &lt;- 10 wech;\r\n\t\/\/ return replace(machLFWeg, &quot;&#92;&#48;15&quot;, &quot;&quot;) &lt;- 13 wech;\r\n\t\r\n\treturn machLFWeg;\r\n}\r\n\r\n\/\/ LTRIM gibts wohl nicht\r\nstring leftTrim(string einString)\r\n{\r\n   int dieLetztePosition=-1;\r\n   for (x=0; x&lt;length(einString); x++)\r\n   {\r\n      if( einString&#x5B;x:x] != &quot; &quot; )\r\n      {\r\n        dieLetztePosition=x;\r\n         break;\r\n      }\r\n   }\r\n\r\n   return einString&#x5B;dieLetztePosition:];\r\n}\r\n\r\n\/\/ RTRIM gibts wohl nicht\r\nstring rightTrim(string einString)\r\n{\r\n   int dieLetztePosition=-1;\r\n   for (x=length(einString)-1; x&gt;=0; x--)\r\n   {\r\n      if( einString&#x5B;x:x] != &quot; &quot; )\r\n      {\r\n        dieLetztePosition=x;\r\n         break;\r\n      }\r\n   }\r\n\r\n   return einString&#x5B;0:dieLetztePosition];\r\n}\r\n\r\n\/\/ Gibt die erste Position eines Strings zur\u00fcck\r\nint indexOf(string testString, string part)\r\n{\r\n\tBuffer buf = create()\r\n\tbuf = testString\r\n\tint index = 0\r\n\twhile(true)\r\n\t{\r\n\t    index = contains(buf, part, index)\r\n\t    if(0 &lt;= index)\r\n\t    {\r\n\t        return index;\r\n\t        index += length(part)\r\n\t    }\r\n\t    else { return -1; break }\r\n\t}\r\n\tdelete(buf)\r\n}\r\n\r\n\/\/ Gibt die erste Position eines zeichens zurueck\r\nint indexOfChar(string derString, string dasZeichen)\r\n{\r\n   int dieLetztePosition=-1;\r\n   \r\n   for (x=0; x&lt;length(derString)-1;x++)\r\n   {\r\n      if( derString&#x5B;x:x] &quot;&quot; == dasZeichen &quot;&quot;)\r\n      {\r\n        dieLetztePosition=x;\r\n         break;\r\n      }\r\n   }\r\n\r\n   return dieLetztePosition;\r\n}\r\n\r\n\/\/ Gibt die Auftretens-Haeufigkeit eines Characters zurueck\r\nint getCharOccurrence(string characterChain, string charToCheckFor)\r\n{\r\n   int countChars=0;\r\n\r\n   for (x=0; x&lt;length(characterChain);x++)\r\n   {\r\n      if( characterChain&#x5B;x:x] &quot;&quot; == charToCheckFor&quot;&quot;)\r\n      {\r\n\t\tcountChars++;\r\n      }\r\n   }\r\n   return countChars;\r\n}\r\n\r\n\/\/ Gibt die erste Position eines zeichens zurueck\r\nint indexOfFrom(string derString, string dasZeichen, int n)\r\n{\r\n   int dieLetztePosition=-1;\r\n   int zeichenCount=0;\r\n   \r\n   for (x=0; x&lt;length(derString)-1;x++)\r\n   {\r\n      if( derString&#x5B;x:x] &quot;&quot; == dasZeichen &quot;&quot;)\r\n      {\r\n      \tzeichenCount++;\r\n      \t\r\n      \tif(zeichenCount!=n)\r\n      \t{\r\n      \t\tcontinue;\r\n      \t}\r\n      \t\r\n        dieLetztePosition=x;\r\n        break;\r\n      }\r\n   }\r\n\r\n   return dieLetztePosition;\r\n}\r\n\r\n\/\/ Gibt die letzte Position eines zeichens zurueck\r\nint lastIndexOf(string derString, string dasZeichen)\r\n{\r\n   int dieLetztePosition=-1;\r\n   \r\n   for (x=length(derString)-1; x&gt;=0; x--)\r\n   {\r\n      if( derString&#x5B;x:x] &quot;&quot; == dasZeichen &quot;&quot;)\r\n      {\r\n        dieLetztePosition=x;\r\n         break;\r\n      }\r\n   }\r\n\r\n   return dieLetztePosition;\r\n}\r\n\r\n\/\/ Alle Zeichen links und rechts abschneiden\r\nstring trim(string einString)\r\n{\r\n\treturn leftTrim(rightTrim(einString)) &quot;&quot;;\r\n}\r\n\r\n\/\/ Ersetze Zeilen in einem String\r\nstring replaceLines(string content, int startLine, int targetLine, string toReplace)\r\n{\r\n\tstring newContent=&quot;&quot;;\r\n\tArray stringLines = split(&quot;\\n&quot;, content);\r\n\tint stringLineCount=getArraySize(stringLines);\r\n\t\r\n\tif(startLine&gt;targetLine)\r\n\t{\r\n\t\treturn &quot;replaceLines: the start index is bigger than the target index&quot;;\r\n\t}\r\n\t\r\n\tif(startLine==-1||targetLine==-1)\r\n\t{\r\n\t\treturn &quot;replaceLines: Select start and target index bigger or equal to zero&quot;;\r\n\t}\r\n\t\r\n\tint i=0;\r\n\tfor(i=0;i&lt;stringLineCount;i++)\r\n\t{\r\n\t\tstring stringZeile=getArrayString(stringLines,i);\t\r\n\t\t\r\n\t\tif(i&gt;=startLine&amp;&amp;i&lt;=targetLine)\r\n\t\t{\r\n\t\t\tif(i==startLine)\r\n\t\t\t{\r\n\t\t\t\tnewContent=newContent &quot;&quot; toReplace &quot;\\n&quot;;\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tnewContent=newContent &quot;&quot; stringZeile &quot;\\n&quot;;\r\n\t\t}\r\n\r\n\t}\r\n\t\r\n\treturn newContent;\r\n}\r\n\r\n<\/pre>\n<iframe src=\"http:\/\/www.facebook.com\/plugins\/like.php?href=https%3A%2F%2Fwww.capri-soft.de%2Fblog%2F%3Fp%3D832&amp;layout=standard&amp;show_faces=true&amp;width=450&amp;action=like&amp;colorscheme=light\" scrolling=\"no\" frameborder=\"0\" allowTransparency=\"true\" style=\"border:none; overflow:hidden; width:450px;margin-top:5px;\"><\/iframe>","protected":false},"excerpt":{"rendered":"<p>Problem DXL besitzt leider nur sehr wenige Stringfunktionen. Man muss sich f\u00fcr einfache Stringmanipulationen eine eigene Bibliothek bauen. DXL consists only of a very less number of string functions. For this purpose you have to implement your own library. Ansatz &#8211; Approach Ich habe die wichtigsten Stringfunktionen aus JAVA\/PHP in eine Bibliothek ausgelagert, die ich &hellip; <a href=\"https:\/\/www.capri-soft.de\/blog\/?p=832\" class=\"more-link\"><span class=\"screen-reader-text\">IBM Doors DXL: Die fehlenden Stringfunktionen \/ The missing String functions<\/span> weiterlesen <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":true,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2},"jetpack_post_was_ever_published":false},"categories":[22,19],"tags":[],"class_list":["post-832","post","type-post","status-publish","format-standard","hentry","category-dxl","category-ibm-doors"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p4yGeN-dq","jetpack_likes_enabled":true,"jetpack-related-posts":[],"_links":{"self":[{"href":"https:\/\/www.capri-soft.de\/blog\/index.php?rest_route=\/wp\/v2\/posts\/832","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.capri-soft.de\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.capri-soft.de\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.capri-soft.de\/blog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.capri-soft.de\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=832"}],"version-history":[{"count":11,"href":"https:\/\/www.capri-soft.de\/blog\/index.php?rest_route=\/wp\/v2\/posts\/832\/revisions"}],"predecessor-version":[{"id":2739,"href":"https:\/\/www.capri-soft.de\/blog\/index.php?rest_route=\/wp\/v2\/posts\/832\/revisions\/2739"}],"wp:attachment":[{"href":"https:\/\/www.capri-soft.de\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=832"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.capri-soft.de\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=832"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.capri-soft.de\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=832"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}