[info]en_dmitriid


Tigers, and lions, and bears, oh my!


Coldfusion и XML
happy
[info]dmitriid
It is a major pain in the nether regions of the body to work with a language which provides reasonable tools for working with XML and provides no sane tools to modify XML. I'm talking about ColdFusion.

Suppose we have the following piece of XML:
<xml>
    <root>
        <elem>
            <value>Text</value>
        </elem>
    </root>


If we read this piece into a variable called xmlDoc, we have immedate access to the value "Text":

txt = xmlDoc.root.elem.value.xmlText;


Now txt contains, as you may have guessed it, a string, "Text".

Moreover, if we have quite a handful of such elements, we may use an extremely convenient function XMLSearch which accepts (an unspecified subset of) XPath and returns an array of found elements.

A real-world example now. Here's a stripped-down localization file from the project I'm working on::

<?xml version="1.0" encoding="UTF-8"?>
<strings>
	<nspace NAME="global">
		<string CRC="73FB418E8CCD929E219338A555AA7EA4">
			<original>You need to login first</original>
			<localized/>
		</string>
		<string CRC="99DEA78007133396A7B8ED70578AC6AE">
			<original>Login</original>
			<localized/>
		</string>
	</nspace>
	<controller NAME="admin">
		<action NAME="cities">
			<string CRC="FD8459135F9464065B708800B0BDF6D8">
				<original>Add a new city</original>
				<localized/>
			</string>
			<string CRC="F67FDD86A499050E0585BCA9EA023188">
				<original>Add city</original>
				<localized/>
			</string>
			<string CRC="4505DE1F3D02176AA6F1403778C5ADD1">
				<original>Region:</original>
				<localized/>
			</string>
		</action>
	</controller>
</strings>


Searching across this monster of a file is trivial:
searchString = "/strings/controller[@NAME=""admin""]/action[@NAME=""cities""]/string[@CRC=""CRC""]";
elems = XmlSearch(xmlDoc, searchString);

/* If there's only one elems, we return it (simplified example): */

return elems[1].localized.xmlString;
where CRC is calculated using obscure Vodoo rituals :)

Now, the question is: what if we want to change the value oа this element? The procedure required to do that evokes an unbearable desire to nuke Macromedia offices :)

Scanning thorugh the docs reveals that the only standard procedure to change the desired value of a tag involves the use of ArrayAppend function on the array of "value" from the array of "elem" from the array of "root"...

That is... You can find an element, but you cannot manipulate it directly. You have to take the root element. Then you have to take an array of first-level elements anв find the desired one. In that element you once again take an array (of second-level elements) and find the desired one. In that element you take an array of third-level elements and find the desired one. And finally, you take an array of fourth-level elements and find the desired one. If such an element does not exist, you append it to the array of fourth-level elements. Save.

Anyway, here's what it looks like in the end:
// Add a new string
ArrayAppend(xmlDoc.strings.xmlChildren[controllersIndex].action[actionsIndex].XmlChildren, XMLElemNew(xmlDoc, "string"));

// Find its position
stringIndex = ArrayLen(xmlDoc.strings.xmlChildren[controllersIndex].action[actionsIndex].XmlChildren);

// Change its attribute
xmlDoc.strings.xmlChildren[controllersIndex].action[actionsIndex].string[stringIndex].xmlAttributes.crc = Hash(t);

// Add "original" to it
ArrayAppend(xmlDoc.strings.xmlChildren[controllersIndex].action[actionsIndex].string[stringIndex].xmlChildren, XMLElemNew(xmlDoc, "original"));

// Find original's position
orgIndex = ArrayLen(xmlDoc.strings.xmlChildren[controllersIndex].action[actionsIndex].string[stringIndex].xmlChildren);

// Add text
xmlDoc.strings.xmlChildren[controllersIndex].action[actionsIndex].string[stringIndex].original.xmlText = t;

// Add "localized"
ArrayAppend(xmlDoc.strings.xmlChildren[controllersIndex].action[actionsIndex].string[stringIndex].xmlChildren, XMLElemNew(xmlDoc, "localized"));

// Obtain its index
locIndex = ArrayLen(xmlDoc.strings.xmlChildren[controllersIndex].action[actionsIndex].string[stringIndex].xmlChildren);

// Add text
xmlDoc.strings.xmlChildren[controllersIndex].action[actionsIndex].string[stringIndex].localized.xmlText = '';


:)))

I am only grateful that I had to write this function only once. And it took me the better part of the day...

A web programmer's lament
happy
[info]dmitriid
Web programmers are generally viewed as "less-than-programmers". Some even think that they are not programmers at all, come to think of it. Indeed, some think that creating something like Codeproject is a piece of cake. Those same people also think that creating a yet another accounting program in Visual Basic (or, god forbid, VBA) is uber-cool and is worthy of all praise.

Now, why would anybody think that? Huh?

Let's consider the so-called "application programmer". Or even the so-called "systems programmer". All they ever need to know is their favorite programming language (C/C++/Java/Object Pascal...). Well, quite often something like a passing knowledge of SQL comes along and a declarative language to store application settings in (usually the INI file format or XML). In toto - at most three technologies: programming language, SQL, XML, and chances are the programmer will use datasets and MSXML to work with the latter to.

What about the web programmer, then?

  • Favorite programming language - one of PHP/Ruby/Perl/Java/C#/Python

  • SQL

  • HTML

  • CSS

  • JavaScript (sometimes with an added bonus of JSON)

  • and quite often XML


Also throw in the bag the fact that web programming is originally and immediately a client-server programming. Most of application programmers don't even have a clue about what's that all about.

So, what we have in the end is that the despised web programmers actually know and do the following:

  • They program client-server applications easily and effortlessly

  • They combine imperative and declarative programming seamlessly

  • They have a more-than-passing knowledge about about non-compatible and non-intersecting technologies and know how to combine them


And as soon as the project starts to grow... We have data replication, distributed servers and son on and so forth...

And still web programming is perceived to be a child's play whereas grown-ups are off working on their "serious" technologies which are supposedly to hard for a web-programmer to comprehend. Well, think again, lads. It is we, web porgrammers, who look down on you because most of the technologies most of you are just beginning to toy with have already been seen, learned and taken to use by us.

BTW, this discrimination against web programming is exactly the reason why web programmers are so behind on tools and libraries. It is only recently that decent tools have sprung up all over the place (such as Ruby on Rails, Django, Seam, Prado and others)

Now that's a bloody shame if you ask me.

WTF
happy
[info]dmitriid
As I promised, this entry will contain code I submitted to The Daily WTF. Of course, my code cannot even compete with the true gems of TheDailyWTF, but here goes...

We're using Symantec WinFax Pro. Among other things it provides a set of COM objects that allow a programmer to manipulate incoming/outgoing faxes, read their status, send faxes etc. One of the main objects is the CSDKLog object. It provides to quite important (no pun or irony intended) functions:

  BSTR GetMessageDate(BSTR MessageID)
  BSTR GetMessageTime(BSTR MessageID)
 

Note that these two functions return a BSTR (for those of you who are lucky not to know this it means Yet Another C++ String Class, Com-style). Ok, it's fine by me as long as this string contains some sort of standard code. Let's say "20062306" and "231451" for "11:14:51 PM, June 23rd, 2006". Yeah right. Both return a locale-formatted string. WTF you ask? Here's TF:

Let's take the aforementioned "11:14:51 PM, June 23rd, 2006". GetMessageDate and GetMessageTime return:
  US locale:    06/23/2006    11:14:51 РМ
  RU locale:    23.06.2006    23:14:51
 
and so on

At least three computers in our office have US Locale. The rest use identical (as far as date/time display is concerned) Ru and TR locales. What will a programmer do? He will do the following::
           static bool isUSDate(char* date)
	{
		std::string df(date);

		int i = df.find('/');

		return i > 0;
	}

	static int dayFromUSDate(char* date)
	{
		std::string df(date);

		df = df.substr(df.find('/') + 1);
		df = df.substr(0, df.find('/'));

		return atoi(df.c_str());
	}

	static int monthFromUSDate(char* date)
	{
		std::string df(date);

		df = df.substr(0, df.find('/'));

		return atoi(df.c_str());
	}

	static int yearFromUSDate(char* date)
	{
		std::string df(date);

		df = df.substr(df.find('/') + 1);
		df = df.substr(df.find('/') + 1);

		return atoi(df.c_str());
	}

	static int dayFromEuDate(char* date)
	{
		std::string df(date);

		df = df.substr(0, df.find('.'));

		return atoi(df.c_str());
	}
	static int monthFromEuDate(char* date)
	{
		std::string df(date);

		df = df.substr(df.find('.') + 1);
		df = df.substr(0, df.find('.'));

		return atoi(df.c_str());
	}
	static int yearFromEuDate(char* date)
	{
		std::string df(date);

		df = df.substr(df.find('.') + 1);
		df = df.substr(df.find('.') + 1);

		return atoi(df.c_str());
	}

	static int hourFromTime(char* date)
	{
		std::string df(date);

		df = df.substr(0, df.find(':'));

		return atoi(df.c_str());
	}

	static int minuteFromTime(char* date)
	{
		std::string df(date);

		df = df.substr(df.find(':') + 1);
		df = df.substr(0, df.find(':'));

		return atoi(df.c_str());
	}
	static int secondFromTime(char* date)
	{
		std::string df(date);

		df = df.substr(df.find(':') + 1);
		df = df.substr(df.find(':') + 1);

		df = df.substr(0, df.find(' ')); /* Brit/US AM/PM */
		df = df.substr(0, df.find('P'));
		df = df.substr(0, df.find('A'));

		return atoi(df.c_str());
	}
 


:))))))))))) What else could I do? I had deadlines, man....

Tags: , ,

Home