Love Fuel?    Donate

FuelPHP Forums

Ask your question about FuelPHP in the appropriate forum, or help others by answering their questions.
Best way to avoid invalid XML formatting in API output?
  • I built an API that is used by an iPhone app. It has a hierarchic user model defined by categories structured according to the modified preorder tree traversal method. Part of the user model is prepared using Arr::flatten(), which results in an array that looks something like this (in JSON):

                "all": {
                    "70:0": "99",
                    "60:0": "101",
                    "60:1": "102",
                    "50:0": "103",
                    "50:1": "104",
                    "50:2": "105",
                    "50:3": "106",
                    "50:4": "107",
                    "50:5": "108",
                    "50:6": "109",
                    "50:7": "110",
                    "30:0": "111",
                    "30:1": "112",
                    "30:2": "113",
                    "30:3": "114"
                }

    The iOS developer I am working with is passing "Accept: application/xml", which results in the following output:

                <all>
                    <700>99</700>
                    <600>101</600>
                    <601>102</601>
                    <500>103</500>
                    <501>104</501>
                    <502>105</502>
                    <503>106</503>
                    <504>107</504>
                    <505>108</505>
                    <506>109</506>
                    <507>110</507>
                    <300>111</300>
                    <301>112</301>
                    <302>113</302>
                    <303>114</303>
                </all>

    The Objective-C XML parser can't parse the data because, well, it's invalid. Changing the "glue" doesn't help. What's the best way to avoid this invalid data?
  • Either construct an array that contains valid XML data server side, or tell the iOS developer that XML is so 20th century, and have him (her?) switch to JSON.
  • Don't get me wrong, I'm a JSON guy. I detest XML, but for whatever reason, these iOS and Unity developers are still all up in XML's business. It's not really *my* problem, but I'm the guy who gets stuck resolving any issue that isn't immediately obvious to the mobile guys, so it becomes *my* problem.

    The problem with "constructing an array that contains valid XML data" is that the web application was developed before the API, and if I change the format of the user model, it will break the entire application. It would be much much simpler if Format::to_xml() checked against a valid-key regular expression. I realize that my pull request added significant overhead to the Format::to_xml() function. Would you guys be more receptive to a pull request that didn't add significant overhead? For example, what if, instead of "if (is_numeric($key))" we used "if (!preg_match('`[a-zA-Z_][a-zA-Z0-9_\.-]`', $key))" to determine if the string key needs to be generated?
  • to_xml() can't check.

    Well. it could check, but would be forced to throw an exception on a violation. And that would not help you one single bit. Any code to "fix" it in to_xml() would be application specific (your fix might differ from my fix).

    So you should not fix it in to_xml(), you should fix the source data in your controller before to_xml() is called.
  • to_xml() currently checks for numeric keys without throwing an exception on violation. Currently, it does this:

    // no numeric keys in our xml please!
    if (is_numeric($key))
    {
    // make string key...
    $key = (\Inflector::singularize($basenode) != $basenode) ? \Inflector::singularize($basenode) : 'item';
    }

    If it "can't check" and it is up to me to make sure that the data passed to Format::to_xml() is valid, shouldn't this code be omitted completely? I'm simply suggesting:

    // no invalid keys in our xml please!
    if ( ! preg_match('`[a-zA-Z_][a-zA-Z0-9_\.-]`', $key))
    {
    // make string key...
    $key = (\Inflector::singularize($basenode) != $basenode) ? \Inflector::singularize($basenode) : 'item';
    }

    This wouldn't throw an exception, it would just treat invalid keys like it currently treats numeric keys (which are also invalid).
  • That means that on every row a very expensive regex is run, while the chance that you need it is very small. So I'm not in favour of it, it would slow things down unnecessary for everyone.
  • HarroHarro
    Accepted Answer
    What might be an option is to move the preg_replace() after that if, to before the if.

    That would change "70:12" to "7012", which is numeric, and would trigger the if without additional processing needed.
  • Brilliant! Shall I create a pull request?
  • Yes, please.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

In this Discussion