So if I discover...
Sort of ish, maybe but no, there is various solutions.
Lets make the example problem a little more concrete, then solve it.
Let us say that for the URL http://acmesite.com/?action=get_foo you need to load, modify and output an XML file called foo.xml
listing of foo.xml
------------------
<foos>
<foo>
<a>I pity the foo</a>
<b>foo bar</b>
<c>foo cough</c>
<d>baz bar foo</d>
</foo>
<foo>
<a>...
<b>...
...
</foo>
...
...
</foos>
And just to make the problem harder still let's also say that you wish to set all the values in any instance of <b> and <d> to upper-case.
Now as it stands with the current plugin set, none of the tags contained in foo actually correspond to any known plugin/symbol name, so if you didn't need to edit the file you would simply include it using <insertfile> (note, the plugins <inc> and <use> refer to aXML files only since they append the string '.aXML' to the path given)
(insertfile)foo.xml(/insertfile)
"<d>" in previous examples was metadata only and I will come back to that in a minute.
There are two ways I can think of to do this..
Method 1
Since we want to edit the values contained in "b" and "d" and since these two tags are not currently defined, we simply define them in the local private subs module that is specific to this action. (you can define them in the site global subs, or in the engine global subs if you want the plugin code to be accessible in a broader scope)
Using this method we are going to need to use the specials. I've not done huge amounts with these specials before, because I haven't used aXML much at all in the way you guys want to use it, and I've had the luxury of being able to design all the data which is put into the system. These examples you have given have made me realise there is actually a call for 6 specials not 4 as I had previously thought, but that's not a problem and I have just added a couple of extra lines to the system so it now supports all 6 specials with this new standardised schema:
In the doc |
In the output |
Name |
&lab; |
< |
"left angle bracket" |
&rab; |
> |
"right angle bracket" |
&lcb; |
( |
"left curved bracket" |
&rcb; |
) |
"right curved bracket" |
&lsb; |
< |
"left square bracket" |
&rsb; |
> |
"right square bracket" |
in your perl subs module for this action
----------------------------------------
$plugins = {
b => sub {
my $data = uc($_[1]);
"&lab;b&rab;$data&lab;/b&rab;"
},
d => sub {
my $data = uc($_[1]);
"&lab;d&rab;$data&lab;/d&rab;"
}
};
That is all, now when you view the file, you will find that the contents of <b> and <d> have been uppercased and the remainder of the document has been untouched.
It would also be possible to do what ikegami suggested earlier and define a plugin which outputs the specials so if I added such a plugin to the standard set, with code like this;
lab => sub { "&lab;$_[1]&rab;" }
your plugin could look like this;
$plugins = {
b => sub {
my $data = uc($_[1]);
"<lab>b</lab>$data<lab>/b</lab>"
},
d => sub {
my $data = uc($_[1]);
"<lab>d</lab>$data<lab>/d</lab>"
}
};
The result is slightly longer code, but it's a lot more readable.
Method 2
This is a simpler method, and this is probably the method I would of normally used prior to the extra thinking about the issue with the specials that I have just done.
It starts off the same:
(insertfile)foo.xml(/insertfile)
Now we are going to define a new plugin to do the transform of the <d> and <b> and wrap it around the insertfile statement so that the output of the insert file falls within it's scope:
<do_transform>
(insertfile)foo.xml(/insertfile)
</do_transform>
The code for the <do_transform> sub is once again defined in the private subs file for this action
$plugins = {
do_transform => sub {
my $data = $_[1]; #grab all the data
$data =~ s@<b>(.*?)</b>@ do { my $uc = uc($1); "<b>$uc</b>"
+}@e;
$data =~ s@<d>(.*?)</d>@ do { my $uc = uc($1); "<d>$uc</d>"
+}@e;
return $data;
}
};
Now lets get back to the issue with <d>, which as I mentioned is not actually a sub but just a bit of metadata that <db_select> uses.
The problem here is that if we wanted to generate foos.xml from a database, the <d> tag in foos.xml would conflict with the <d> tag used by the <db_select> tag. Recall that outside of the scope of a <db_select> <d> has no meaning and therefore is not a problem.
<foos>
<db_select>
<query> SELECT * FROM foo</query>
<mask>
<foo>
<a><d>a</d></a>
<b><d>b</d></b>
<c><d>c</d></c>
<d><d>d</d></d> // oh dear...
...
...
We can solve this in a couple of ways.
Solution 1
You could overload the <db_select> tag with one of your own design which works with your
input data, for instance you could modify it to use <col> as the column delimiter instead of <d>.
Solution 2
I could modify db_select to take an extra argument to determine the column delimiter (I think I will infact be making this change.)
<foos>
<db_select delimiter="col">
<query> SELECT * FROM foo</query>
<mask>
<foo>
<a><col>a</col></a>
<b><col>b</col></b>
<c><col>c</col></c>
<d><col>d</col></d> // that's better :)
...
...
Now lets say you don't know ahead of time what tagnames are going to be in the XML, and you want to make absolutely sure your not going to get a conflict.
What we could do is define a plugin which deletes all the plugins, and adds in a couple of new ones which you design specifically for this action.
$plugins = {
delete_all => sub { $plugins = {
load => sub {... },
transform => sub {... }
};
}
};
Then in your document you call <delete_all> then call on the new subs to do what you need to do (I.E, load and modify the file).
(delete_all)(/delete_all)
<transform>
<load>foo.xml</load>
</transform>
Or something like that, use your imagination your a programmer.
P.s, if their is any stupid mistakes in the above I'm sorry but I've been looking at the screen for about 12 hours now and I'm about to go hit the sack.
|