Search code examples
xmllualua-patterns

Lua pattern replacement


Got the following XML structure:

<?xml version="1.0" encoding="UTF-16"?>
<xml>
   <v id="Node_Name_1">Node_1_Value</v>
   <v id="Node_Name_2">Node_2_Value</v>
   <v id="Node_Name_3">Node_3_Value</v>
   <v id="Node_Name_4">Node_4_Value</v>
</xml>

The structure above is returned by a web service as String, what I want is to transform that structure into:

<?xml version="1.0" encoding="UTF-8"?>
<xml>
   <Node_Name_1>Node_1_Value</Node_Name_1>
   <Node_Name_2>Node_2_Value</Node_Name_2>
   <Node_Name_3>Node_3_Value</Node_Name_3>
   <Node_Name_4>Node_4_Value</Node_Name_4>
</xml>

This is my code:

local pattern = '(<v id="(.+)">(.+)</v>)'
local rplcmnt = "<%1>%2</%1>"
local endXml = string:gsub(orgXml, pattern, rplcmnt)
local endStr = "<?xml version='1.0' encoding='UTF-8'?><xml>"..endXml.."</xml>"

The problem is that the pattern returns the whole content of node and at replacing stage it takes first node name, create the tag and then uses it for wrap everything else.


Solution

  • Try this:

    local pattern = '(<v id="(.-)">(.-)</v>)'
    local rplcmnt = "<%2>%3</%2>"
    local endXml = string.gsub(orgXml, pattern, rplcmnt)
    

    The differences from your code are:

    • the use of non-greedy match .- instead of .+.

    • the correct replacement pattern, because everything in Lua starts at 1 instead of 0.

    • the use of string.gsub instead of string:gsub.
      You could also use orgXml:gsub(pattern, rplcmnt).