This article, from April had a problem, so they decided to use XML. Now they have An error occurred while parsing EntityName. Line 7, position 32. -- Remy

Once you eliminate the impossible…

…Whatever remains, no matter how improbable, must be XML.

William Hogarth - Absurd perspectives.png

Developers have many weaknesses, among them this: they don’t like to say that something can’t be done. That’s why when Glenn M’s client, TelCo, asked if their request was really impossible, instead of apologizing and vigorously nodding his head, Glenn said, “Well, technically…”

And that’s how he ended up writing this.

<value>
    <mult>
        <op>
            <mult>
                <op>
                    <add>
                        <op>
                            <div>
                                <op>
                                    <bitwise_and>
                                        <op>
                                            <baseNToInt base="16">
                                                <regex>
                                                    <op>(?:0x)?([0-9a-fA-F][0-9a-fA-F])\s*([0-9a-fA-F][0-9a-fA-F])\s*([0-9a-fA-F][0-9a-fA-F])\s*([0-9a-fA-F][0-9a-fA-F])</op>
                                                    <op><getRowOid>.1.3.6.1.4.1.2011.2.217.1.4.1.1.6</getRowOid></op>
                                                    <op>%4$s%3$s%2$s%1$s</op>
                                                </regex>
                                            </baseNToInt>
                                        </op>
                                        <op>8388607</op>
                                    </bitwise_and>
                                </op>
                                <op>8388608</op>
                            </div>
                        </op>
                        <op>1</op>
                    </add>
                </op>
                <op>
                   <left_shift>
                       <op>1</op>
                       <op>
                           <sub>
                               <op>
                                   <bitwise_and>
                                       <op>
                                           <right_shift>
                                               <op>
                                                   <baseNToInt base="16">
                                                       <regex>
                                                           <op>(?:0x)?([0-9a-fA-F][0-9a-fA-F])\s*([0-9a-fA-F][0-9a-fA-F])\s*([0-9a-fA-F][0-9a-fA-F])\s*([0-9a-fA-F][0-9a-fA-F])</op>
                                                           <op><getRowOid>.1.3.6.1.4.1.2011.2.217.1.4.1.1.6</getRowOid></op>
                                                           <op>%4$s%3$s%2$s%1$s</op>
                                                       </regex>
                                                   </baseNToInt>
                                               </op>
                                               <op>23</op>
                                           </right_shift>
                                       </op>
                                       <op>255</op>
                                   </bitwise_and>
                               </op>
                               <op>127</op>
                           </sub>
                       </op>
                   </left_shift>
               </op>
           </mult>
       </op>
       <op>
           <if>
               <op>
                   <eq>
                       <op>
                           <bitwise_and>
                               <op>
                                   <right_shift>
                                       <op>
                                           <baseNToInt base="16">
                                               <regex>
                                                   <op>(?:0x)?([0-9a-fA-F][0-9a-fA-F])\s*([0-9a-fA-F][0-9a-fA-F])\s*([0-9a-fA-F][0-9a-fA-F])\s*([0-9a-fA-F][0-9a-fA-F])</op>
                                                   <op><getRowOid>.1.3.6.1.4.1.2011.2.217.1.4.1.1.6</getRowOid></op>
                                                   <op>%4$s%3$s%2$s%1$s</op>
                                               </regex>
                                           </baseNToInt>
                                       </op>
                                       <op>31</op>
                                   </right_shift>
                               </op>
                               <op>1</op>
                           </bitwise_and>
                       </op>
                       <op>1</op>
                   </eq>
               </op>
               <op>-1</op>
               <op>1</op>
           </if>
       </op>
   </mult>
</value>  

That’s an XML DDF, a Data-Definition File for the systems-monitoring application Glenn supports. See, the system can read data from any device that supports the Modbus/TCP or SNMP protocols, as long as it has a DDF file that defines the data points and how they’re to be displayed. The DDF schema includes the arithmetic, boolean, regex, and conditional operators you see above, to let the system know how the data should be cleaned up.

Logic via XML? That’s a WTF all by itself, sure. But TRWTF is what that snippet above is actually doing. TelCo was monitoring a device that spat out temperature values (simple enough), but it presented them as an eight-character string representing the hexadecimal value of an IEEE–754 32-bit floating-point number. The task that Glenn probably should have said was impossible was to cast that bizarre value back into its numeric equivalent. DDF, for all its awesome expressive power, lacked a typecast operator.

That’s why Glenn wrote the DDF shown above, which does this:

  • Since the byte order was flipped, use <regex> to put them back in an order we can work with
  • Use <baseNtoInt> to convert from octetString to uint_32
  • Use <bitwise_and> and <right_shift> to isolate the sign bit, exponent and mantissa
  • Convert the sign bit to +/–1
  • Unbias the exponent, then <left_shift> 1 by that many
  • Divide the mantissa by 2^23
  • Multiply the last three items together to get the final result. Since <mult> and other operators only accept 2 operands, these need to be nested

Next time, Glenn plans to stick to his guns, because he just heard that TelCo will be modifying their device to present temperature using integers.

[Advertisement] Release! is a light card game about software and the people who make it. Play with 2-5 people, or up to 10 with two copies - only $9.95 shipped!