The MivaScript tag MvCALL emulates a browser call to a host. You can use it to request or post to HTML, XML, and SGML pages. When you request a page, the page data is returned one tag at a time inside the MvCALL loop.
Basic Method to Display Web Content with MvCALL
<MIVA STANDARDOUTPUTLEVEL = "compresswhitespace,text,html">
<MvCALL ACTION = "http://www.barchartmarketdata.com/data-samples/us-options-futures-eod.xml" METHOD = "GET" FIELDS = "">
<MvEVAL EXPR = "{encodeentities(s.callvalue)}">
</MvCALL>
The script above starts with the MIVA STANDARDOUTPUTLEVEL which tells the server what to output. The more complex your scripts get the more you have to be aware of leaking whitespace into your output.
When you use MvCALL to get page data from a website it will loop through each tag and assign the output to a system variable called s.callvalue.
In the example script above, the s.callvalue variable is evaluated using MvEVAL and the encodeentities(...) MivaScript function. The encodeentities(...) function is one to get to know because it takes unreadable and/or potentially harmful scripting/text and turns it into HTML character codes that you can safely output.
The METHOD is either GET or POST depending on how you are interacting with a web page. If you want to post some fields to a remote web page, you would put those into the FIELDS area.
Posting Fields with MvCALL
Let's say you want to post a login to a remote web page. We'll assign some values to a username and password field and then use MvCALL to post it to somepage.mvc.
<MvASSIGN NAME = "l.username" VALUE = "{ 'Scot' }">
<MvASSIGN NAME = "l.password" VALUE = "{ '123mypass' }">
<MvCALL ACTION = "somepage.mvc" METHOD = "POST" FIELDS = "l.username,l.password">
</MvCALL>
SOMEPLACE.MVC is a random filename I invented for this, but normally you would post fields to a script such as MivaScript or PHP or some other web page that was designed to handle data being sent to it.
Getting Website Text Only - Skip Tags
MvCALL gives us an easy way to strip the tags from a web page and just get the text.
<MvCALL ACTION = "http://www.scotsscripts.com" METHOD = "GET" FIELDS = "">
<MvIF EXPR = "{ s.callobjecttype EQ 'tag'}">
<MvCALLCONTINUE>
</MvIF>
<MvIF EXPR = "{trim(s.callvalue)}">
<MvEVAL EXPR = "{encodeentities(s.callvalue)}">
</MvIF>
</MvCALL>
In this example we use MvCALL to collect page data from home page of scotsscripts.com. We skip most tags by checking the system variable s.callobjecttype to see if it's been set to 'tag' (the MivaScript environment will automatically set system variables.) If it has, we use MvCALLCONTINUE to begin the next MvCALL loop immediately.
You'll notice that the script above still lets through quite a few tags. Javascript, style sheets, header information, a lot of it shows up. You could alleviate a lot of that by putting in some switches that monitor the opening and closing body tags.
Even with this, javascript and stylesheets placed inside the body show up. In this case, we'll add a couple more items to monitor such as the script and style tags.
<MvCALL ACTION = "http://www.scotsscripts.com" METHOD = "GET" FIELDS = "">
<MvIF EXPR = "{ s.callobjectelement EQ 'body' OR
s.callobjectelement EQ '/script' OR
s.callobjectelement EQ '/style'}">
<MvASSIGN NAME = "l.output" VALUE = "{ 'on' }">
</MvIF>
<MvIF EXPR = "{ s.callobjectelement EQ '/body' OR
s.callobjectelement EQ 'script' OR
s.callobjectelement EQ 'style'}">
<MvASSIGN NAME = "l.output" VALUE = "{ 'off' }">
</MvIF>
<MvIF EXPR = "{l.output EQ 'on'}">
<MvIF EXPR = "{ s.callobjecttype EQ 'tag'}">
<MvCALLCONTINUE>
<MvELSE>
<MvIF EXPR = "{trim(s.callvalue) AND s.callobjectelement NE 'script'}">
<MvEVAL EXPR = "{encodeentities(s.callvalue)}">
</MvIF>
</MvIF>
</MvIF>
</MvCALL>
As you can see, by turning the output switch on or off based on the opening or closing tags, we can totally control the output. You could go further with this. Let's say you wanted to get rid of menu items which are usually list elements, you could monitor paragraph tags and only output data found inside paragraph tags.
We use the MivaScript trim(...) function to get rid of all trailing and leading whitespace in the s.callvalue variable. If there is still data, we use the MvEVAL MivaScript tag to display it. It's good practice to use the MivaScript function encodeentities(...) when displaying potentially harmful data, and even though this script automatically strips out anything that's not plain text, it's always a good practice to be safe.
Other MvCALL System Variables
- s.callvalue: the entire tag, including angle brackets and attributes, as-is from the webpage.
- s.callobjecttype: set to 'tag' or 'text'.
- s.callobjectelement: if s.callobjecttype is set to 'tag', this variable contains the tag name. A closing tag will begin with a slash / symbol.
- s.callobjectnumattributes: the number of attributes specified for the tag.
- s.callobjectattributeN: if the tag has attributes, they are put in a pseudo-array based on s.callobjectattribute and followed by a number. For example, s.callobjectattribute1 is the first attribute, s.callobjectattribute2 is the second. See below for an example of how to roll through this kind of array.
- s.callobjectvalueN: attribute values in a pseudo-array. See above.
- s.callnumberofheaders: contains the number of headers that have been retrieved and will not change during the MvCALL loop.
- s.callreturnheaderN: a pseudo array containing the headers. See the s.callobjectattributeN description above.
You can loop through these pseudo-arrays using the MivaScript function miva_variable_value(..) quite easily:
<MvASSIGN NAME = "l.pos" VALUE = "{ '' }">
<MvWHILE EXPR = "{l.pos NE s.callobjectnumattributes}">
<MvASSIGN NAME = "l.pos" VALUE = "{ l.pos + 1 }">
<MvEVAL EXPR = "{s.callobjectelement $ 'attribute #' $ l.pos $ '. ' $ miva_variable_value('s.callobjectattribute' $ l.pos)}">
</MvWHILE>
You could put this code block directly under the MvCALL opening tag in the example script above to display all the attributes for each tag. We set l.pos to null ('') because we're in a loop and it needs to start at 0 each time.
The MivaScript function miva_variable_value(...) will give you the value of a dynamically created variable name and is useful for things like this.
Full documentation on MvCALL can be found in the online MivaScript guide here:
http://www.mivascript.com/item/mivascript-tags/MvCALL.html