65.9K
CodeProject 正在变化。 阅读更多。
Home

适配 GRML

starIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIconemptyStarIcon

1.55/5 (8投票s)

2004年9月3日

6分钟阅读

viewsIcon

98184

downloadIcon

177

将 HTML 网页转换为 GRML。

引言

本文介绍了将网页从一种标记语言适配(或转换)到另一种标记语言的过程。它讨论了如何将 HTML 网页适配到 GRML。提供了两个示例。第一个演示了如何从 HTML 网页中提取超链接并将其转换为 GRML。第二个演示了如何对图像执行此操作。这些示例需要服务器端处理。在这里,使用了 IIS、Active Server Pages (ASP) 和 PERL。

背景

建议您具备一些 ASP 和 PERL 的经验。 PERL 具有正则表达式支持,用于从网页中提取超链接和图像。任何服务器端脚本编写环境都可以做到这一点,包括 .NET、CGI 或 PHP。但是,本文使用了 PERL 和 ASP。虽然 PERL 是必需的,但专门使用的服务器端脚本编写语言是 PerlScript。要使用 PerlScript,请下载 PERL 解释器。要获取一个与 IIS 配合使用的解释器,请尝试 ActivePerl。如果尚未完成,请阅读 介绍 GRML使用 GRML。这些文章解释了什么是 GRML 以及如何使用它。

什么是适配器?

适配器通常定义为...

将组件的原始接口转换为另一个接口的对象。

对于本文而言,适配器的定义是...

将一种标记语言转换为另一种标记语言的服务器端处理或脚本。

此定义描述了使用 ASP 将 HTML 转换为 GRML。适配器对象是 ASP 脚本,原始接口是 HTML,另一个接口是 GRML。

根据要转换的内容,适配器需要从原始接口读取并写入另一个接口。换句话说,适配器需要一个接口读取器和一个接口写入器。一个 HTML 到 GRML 适配器需要一个 HTML 读取器和一个 GRML 写入器。

适配超链接和图像

HTML 没有描述其内容的许多元素。例如,无法确定一个文本块的属性与另一个文本块的属性有何不同。但是,并非所有 HTML 内容都没有描述。它确实有用于超链接和图像的特定标签。

使用特定标签来标识内容可以创建一个仅读取这些标签的脚本。找到时,不必要的标签元素将被删除,只留下内容。然后,脚本以新格式或标记语言写入内容。这就是它如何将 HTML 超链接或图像适配到 GRML 的方式。

超链接适配器

使用 <a href=> 标签允许 HTML Web 浏览器识别哪些文本是超链接。此标签是超链接适配器的基础。它从 HTML 网页中提取所有超链接,并将它们转换为 GRML。

以下是使用 PerlScript 的 HTML 到 GRML 超链接适配器的示例

<%@ Language="PerlScript%">
<HTML>
<center>
<form action=links.asp>
URL to extract: <input type=text name=url1 length=60>
<input type=submit>
</form>
</center>
<!--
<grml>
<edit url1>
<title>Enter URL:>
<%
use HTML::LinkExtor;
use URI::URL;
use LWP;

my $url, $html;

# Parsing the Request
$url = $Request->QueryString("url1")->Item();

$Response->Write("<submit>\n");
$Response->Write("<location>GRMLBrowser.com/links.asp\n");
$Response->Write("</submit>\n");
$Response->Write("<edit url1>\n");
$Response->Write("<text>$url\n");
$Response->Write("</edit>\n");

if ($url eq "")
{
        $Response->Write("</GRML>\n");
}
else
{
        if ($url !~ /http:\/\//)
        {
            $url = "http://". $url;
        }
}

# Constructing the Request
    $_ = $sites;

# Retrieving the Response/Resultset
#    - Filtering the Resultset (optional)
my $ua = LWP::UserAgent->new(agent => "Mozilla 4.0");
my $request  = HTTP::Request->new('GET', $url);
my $response = $ua->request($request);

unless ($response->is_success)
{
    print $response->error_as_HTML . "\n";
    exit(1);
}

my $res = $response->content(); # content without HTTP header

$Response->Write("<column>\n");
$Response->Write("<Title>\n");
$Response->Write("<Request>\n");
$Response->Write("<link>\n");
$Response->Write("</column>\n");

$Response->Write("<result>\n");

$res =~ s/\n/ /gsi;

while($res =~ m|href=(.+?)>(.*?)</A>|gsi)   ## that's all ...
{
    my $temp_link = $1;
    my $temp_item = $2;
    
    $temp_link =~ s/\'//gsi;
    $temp_link =~ s/\"//gsi;
    $temp_link =~ s/ (.*)//gsi;
    $temp_link =~ s/<b>//gsi;
    $temp_link =~ s/<\/b>//gsi;
    $temp_link =~ s/&/\&/gsi;
    $temp_link =~ s/\n(.*)//gsi;
    $temp_item =~ s/<b>//gsi;
    $temp_item =~ s/<\/b>//gsi;
    $temp_item =~ s/<(.+?)>//gsi;
    $temp_item =~ s/<\/font>//gsi;
    $temp_item =~ s/&/\&/gsi;
    $temp_item =~ s/ / /gsi;
    $temp_item =~ s/&quot;/\"/gsi;
    $temp_item =~ s/\n(.*)//gsi;
    $temp_item =~ s/\n/  /gsi;
    $temp_item =~ s/  (.*)//gsi;
    $temp_item =~ s/   (.*)//gsi;
   

    if ($temp_item !~ /img src=/)
    {
        if ($temp_link !~ /$url/ && $temp_link !~ /\/\//)
        {
            $temp_link = $url . "\/" . $temp_link;
        }

        $temp_item =~ s/\n//gsi;
        $temp_link =~ s/\n//gsi;

        $Response->Write("<link>$temp_link\n");
        $Response->Write("<title>$temp_item\n");    
    }

    $Response->Write("<request>$url\n");
    $Response->Write("\n\n");
}

$Response->Write("</result>\n");
$Response->Write("</GRML>\n");
%>
-->
</html>

上述代码的作用是在 HTML 中创建一个表单,该表单从网页中提取所有超链接。超链接(及其标题)使用 GRML 格式化。要查看 GRML,需要一个 GRML Web 浏览器(例如 Pioneer Report MDI)。

所有服务器端脚本都用作 HTML 读取器。只有以下几行用作 GRML 写入器。它们是

  • $Response->Write("\n");
  • $Response->Write("\n");</CODE> <LI><CODE lang=perlscript>$Response->Write("<Request>\n");</CODE> <LI><CODE lang=perlscript>$Response->Write("<link>\n");</CODE> <LI><CODE lang=perlscript>$Response->Write("</column>\n");</CODE> <LI><CODE lang=perlscript>$Response->Write("<result>\n");</CODE> <LI><CODE lang=perlscript>$Response->Write("<link>$temp_link\n");</CODE> <LI><CODE lang=perlscript>$Response->Write("<title>$temp_item\n");</CODE> <LI><CODE lang=perlscript>$Response->Write("<request>$url\n");</CODE> <LI><CODE lang=perlscript>$Response->Write("</result>\n");</CODE> </LI></UL> <P>Only the last three lines format the hyperlinks using GRML. The first two lines create the form in the browser window of a GRML web browser and do not use the adapted HTML hyperlinks.</P> <P>To see the above in action, go to <A href="http://grmlbrowser.com/links.asp" target=_blank>Hyperlink adapter</A> or copy the above script to a file and host it from a local web server. Once the web page is displayed, enter a URL and press the 'Submit' button. It displays all the hyperlinks extracted from the HTML web page formatted in GRML.</P> <P>After adapting hyperlinks from HTML to GRML, this is how it appears in a GRML web browser (using Pioneer Report MDI):</P> <P><IMG height=351 src="https://cloudfront.codeproject.com/aspnet/adaptinggrml/prm1_001.jpg" width=425></P> <H2>The Image adapter</H2> <P>Using the <CODE lang=html><span class="code-keyword"><</span><span class="code-leadattribute">img</span> <span class="code-attribute">src</span><span class="code-keyword">=</span><span class="code-keyword">></span></CODE> tag, a script is able to find and extract images from HTML. By reading this tag and removing unwanted tag elements, the HTML images are converted to GRML. The following script demonstrates this:</P><PRE lang=perlscript><span class="code-pagedirective"><%@</span><span class="code-leadattribute"> Language</span><span class="code-keyword">="</span><span class="code-keyword">PerlScript%"</span><span class="code-attribute">> <center> <form action</span><span class="code-keyword">=translate.asp</span><span class="code-attribute">> URL to translate: <input type</span><span class="code-keyword">=text</span><span class="code-attribute"> name</span><span class="code-keyword">=url1</span><span class="code-attribute"> length</span><span class="code-keyword">=60</span><span class="code-attribute">> <input type</span><span class="code-keyword">=submit</span><span class="code-attribute">> </form> </center> <!-- <grml> <edit url1> <title>Enter URL: </edit> <% use HTML::LinkExtor; use URI::URL; use LWP; my $url, $html; # Parsing the Request $url </span><span class="code-keyword">=</span><span class="code-attribute"> $Request->QueryString("url1")->Item(); if ($url eq "") { $Response->Write("</GRML>\n"); } else { if ($url !~ /http:\/\//) { $url </span><span class="code-keyword">= "</span><span class="code-keyword">http://"</span><span class="code-attribute"> . $url; } } $Response->Write("### URL ###\n\n"); $Response->Write("The url is: $url\n\n"); # Constructing the Request $_ </span><span class="code-keyword">=</span><span class="code-attribute"> $sites; # Retrieving the Response/Results # - Filtering the Results (optional) my $ua </span><span class="code-keyword">=</span><span class="code-attribute"> LWP::UserAgent->new(agent </span><span class="code-keyword">=</span><span class="code-attribute">> "my agent V1.00"); my $request </span><span class="code-keyword">=</span><span class="code-attribute"> HTTP::Request->new('GET', $url); my $response </span><span class="code-keyword">=</span><span class="code-attribute"> $ua->request($request); unless ($response->is_success) { print $response->error_as_HTML . "\n"; exit(1); } my $res </span><span class="code-keyword">=</span><span class="code-attribute"> $response->content(); # content without HTTP header my @imgs </span><span class="code-keyword">=</span><span class="code-attribute"> (); my @hrefs </span><span class="code-keyword">=</span><span class="code-attribute"> (); # Make the parser. Unfortunately, we don't know the base yet # (it might be diffent from $url) my $p </span><span class="code-keyword">=</span><span class="code-attribute"> HTML::LinkExtor->new(\&callback); $p->parse($res); # Expand all image URLs to absolute ones my $base </span><span class="code-keyword">=</span><span class="code-attribute"> $response->base; @imgs </span><span class="code-keyword">=</span><span class="code-attribute"> map { $_ </span><span class="code-keyword">=</span><span class="code-attribute"> url($_, $base)->abs; } @imgs; $Response->Write("<column>\n"); $Response->Write("<image>\n"); $Response->Write("<link>\n"); $Response->Write("</column>\n\n"); $Response->Write("<result>\n"); foreach (@imgs) { $Response->Write("<image>$_\n"); } $Response->Write("\nLinks:\n"); foreach (@hrefs) { my $temp </span><span class="code-keyword">=</span><span class="code-attribute"> $_; if ($temp !~ /$url/ && $temp !~ /\/\//) { $temp </span><span class="code-keyword">=</span><span class="code-attribute"> $url . "\/" . $temp; } $Response->Write("<link>$temp\n"); } sub callback { my($tag, %attr) </span><span class="code-keyword">=</span><span class="code-attribute"> @_; push(@imgs , values %attr) if $tag eq 'img'; push(@hrefs, values %attr) if $tag eq 'a'; } </span><span class="code-pagedirective">%></span> <span class="code-keyword"><</span><span class="code-keyword">/</span><span class="code-leadattribute">result</span><span class="code-keyword">></span> <span class="code-keyword"><</span><span class="code-keyword">/</span><span class="code-leadattribute">GRML</span><span class="code-keyword">></span> --></PRE> <P>The above script is used as an HTML reader, except for the lines used to build the columns and each result. These lines are the GRML writer:</P> <UL> <LI><CODE lang=perlscript>$Response->Write("<column>\n");</CODE> <LI><CODE lang=perlscript>$Response->Write("<image>\n");</CODE> <LI><CODE lang=perlscript>$Response->Write("<link>\n");</CODE> <LI><CODE lang=perlscript>$Response->Write("</column>\n\n");</CODE> <LI><CODE lang=perlscript>$Response->Write("<result>\n");</CODE> <LI><CODE lang=perlscript>$Response->Write("<image>$_\n");</CODE> <LI><CODE lang=perlscript>$Response->Write("<link>$temp\n");</CODE> <LI><CODE lang=perlscript>$Response->Write("</result>\n");</CODE> </LI></UL> <P>Once the image content has been adapted to GRML, this is how it looks in a GRML web browser (using Pioneer Report MDI):</P> <P><IMG height=351 src="https://cloudfront.codeproject.com/aspnet/adaptinggrml/prm1_002.jpg" width=425></P> <H2>Conclusion</H2> <P>Converting HTML to GRML is possible when using an adapter. Only the content with identifiable tags are adaptable from one markup language to another. In the case of HTML, there are tags to identify hyperlinks and images.</P> <P>The examples described for adapting content show how to convert HTML hyperlinks or images to GRML. The adapter consists of a HTML reader and a GRML writer. Using this adapter, a web page viewed with a HTML web browser is viewable using a GRML web browser.</P> <H2>Latest changes</H2> <UL> <LI>09/03/04 <UL> <LI>Using GRML v1.2 in code samples. </LI></UL> <LI>10/08/04 <UL> <LI>Using GRML v2.3 in code samples. Pioneer Report MDI 3.64 uses GRML v1.2 while all other GRML web browsers use v2.3. </LI></UL></LI></UL> </div></div></div></div><div><div id="div-gpt-ad-1738591766860-0" style="min-width:300px;min-height:600px" class="mt-40 sticky top-40"></div></div></div><!--$--><!--/$--><!--$--><!--/$--></main><footer class="custom-container flex flex-col gap-3 px-2"><div class="mt-2 py-4 min-h-36 bg-primary"></div><div class="border-t-4 border-primary p-3 flex justify-between"><nav class="flex-1"><ul><li><a href="http://developermedia.com/" rel="nofollow noreferrer">Advertise</a></li><li><a href="/info/privacy.aspx">Privacy</a></li><li><a href="/info/cookie.aspx">Cookies</a></li><li><a href="/info/TermsOfUse.aspx">Terms of Use</a></li></ul></nav><div class="flex-1"></div><div class="flex-1 text-gray text-sm text-right">Copyright © <a href="mailto:webmaster@codeproject.com">CodeProject</a>, 1999-2025<br/>All Rights Reserved.</div></div></footer><script src="#webpack-5ed466aeca77ac7a.js" async=""></script><script>(self.__next_f=self.__next_f||[]).push([0])</script><script>self.__next_f.push([1,"1:\"$Sreact.fragment\"\n2:I[387,[\"869\",\"static/chunks/869-095b567be01917e3.js\",\"177\",\"static/chunks/app/layout-1ea82ab3f50fdbe9.js\"],\"default\"]\n3:I[6874,[\"869\",\"static/chunks/869-095b567be01917e3.js\",\"394\",\"static/chunks/app/article/%5BarticleType%5D/%5BarticleId%5D/%5BarticleSlug%5D/page-1251365ce5bc4953.js\"],\"\"]\n4:I[3063,[\"869\",\"static/chunks/869-095b567be01917e3.js\",\"394\",\"static/chunks/app/article/%5BarticleType%5D/%5BarticleId%5D/%5BarticleSlug%5D/page-1251365ce5bc4953.js\"],\"Image\"]\n5:I[6932,[\"869\",\"static/chunks/869-095b567be01917e3.js\",\"394\",\"static/chunks/app/article/%5BarticleType%5D/%5BarticleId%5D/%5BarticleSlug%5D/page-1251365ce5bc4953.js\"],\"default\"]\n6:I[7231,[\"869\",\"static/chunks/869-095b567be01917e3.js\",\"177\",\"static/chunks/app/layout-1ea82ab3f50fdbe9.js\"],\"default\"]\n7:I[7555,[],\"\"]\n8:I[1295,[],\"\"]\na:I[9665,[],\"MetadataBoundary\"]\nc:I[9665,[],\"OutletBoundary\"]\nf:I[4911,[],\"AsyncMetadataOutlet\"]\n11:I[9665,[],\"ViewportBoundary\"]\n13:I[6614,[],\"\"]\n14:\"$Sreact.suspense\"\n15:I[4911,[],\"AsyncMetadata\"]\n:HL[\"/_next/static/media/945b7384c5256ec3-s.p.ttf\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/ttf\"}]\n:HL[\"/_next/static/media/b55e164a6e7ce445-s.p.ttf\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/ttf\"}]\n:HL[\"/_next/static/media/e337cf18f0f81cb9-s.p.ttf\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/ttf\"}]\n:HL[\"/_next/static/media/f7794ce32483498f-s.p.ttf\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/ttf\"}]\n:HL[\"/_next/static/css/f00fbee724adea66.css\",\"style\"]\n"])</script><script>self.__next_f.push([1,"0:{\"P\":null,\"b\":\"KmxRTrlUit5clwfM6GRk0\",\"p\":\"\",\"c\":[\"\",\"Articles\",\"8170\",\"Adapting-GRML\"],\"i\":false,\"f\":[[[\"\",{\"children\":[\"article\",{\"children\":[[\"articleType\",\"Articles\",\"d\"],{\"children\":[[\"articleId\",\"8170\",\"d\"],{\"children\":[[\"articleSlug\",\"Adapting-GRML\",\"d\"],{\"children\":[\"__PAGE__\",{}]}]}]}]}]},\"$undefined\",\"$undefined\",true],[\"\",[\"$\",\"$1\",\"c\",{\"children\":[[[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/css/f00fbee724adea66.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}]],[\"$\",\"html\",null,{\"lang\":\"en\",\"children\":[[\"$\",\"head\",null,{\"children\":[[\"$\",\"link\",null,{\"rel\":\"apple-touch-icon\",\"sizes\":\"144x144\",\"href\":\"/favicon/apple-touch-icon.png\"}],[\"$\",\"link\",null,{\"rel\":\"icon\",\"type\":\"image/png\",\"sizes\":\"32x32\",\"href\":\"/favicon/favicon-32x32.png\"}],[\"$\",\"link\",null,{\"rel\":\"icon\",\"type\":\"image/png\",\"sizes\":\"16x16\",\"href\":\"/favicon/favicon-16x16.png\"}],[\"$\",\"link\",null,{\"rel\":\"manifest\",\"href\":\"/favicon/manifest.json\"}],[\"$\",\"link\",null,{\"rel\":\"mask-icon\",\"href\":\"/favicon/safari-pinned-tab.svg\",\"color\":\"#ff9900\"}],[\"$\",\"meta\",null,{\"property\":\"og:title\",\"content\":\"CodeProject\"}],[\"$\",\"meta\",null,{\"property\":\"og:image\",\"content\":\"https://codeproject.org.cn/favicon/mstile-150x150.png\"}],[\"$\",\"meta\",null,{\"property\":\"og:description\",\"content\":\"For those who code\"}],[\"$\",\"meta\",null,{\"property\":\"og:url\",\"content\":\"https://codeproject.org.cn\"}],[\"$\",\"script\",null,{\"async\":true,\"src\":\"https://#/tag/js/gpt.js\"}],[\"$\",\"$L2\",null,{}]]}],[\"$\",\"body\",null,{\"className\":\"__className_2277ee\",\"children\":[[\"$\",\"header\",null,{\"children\":[[\"$\",\"div\",null,{\"className\":\"custom-container gap-2 py-1 text-gray-light flex justify-between whitespace-nowrap z-10 relative px-1 md:px-0\",\"children\":[[\"$\",\"div\",null,{\"className\":\"flex-1 md:ml-20\",\"children\":[[\"$\",\"span\",null,{\"className\":\"hidden md:block\",\"children\":[65.938,\" articles\"]}],[\"$\",\"span\",null,{\"className\":\"block md:hidden\",\"children\":[\"65.9\",\"K\"]}]]}],[\"$\",\"div\",null,{\"className\":\"flex-1\",\"children\":[\"CodeProject is changing.\",\" \",[\"$\",\"$L3\",null,{\"href\":\"/info/Changes.aspx\",\"className\":\"!text-gray-lightest\",\"children\":\"Read more.\"}]]}],[\"$\",\"div\",null,{\"className\":\"flex-1\"}],[\"$\",\"div\",null,{\"className\":\"flex-1\"}]]}],[\"$\",\"div\",null,{\"className\":\"mb-2 mt-2 md:mt-0\",\"children\":[\"$\",\"div\",null,{\"className\":\"h-[94px] bg-primary\",\"children\":[\"$\",\"div\",null,{\"className\":\"custom-container relative h-full\",\"children\":[[\"$\",\"$L3\",null,{\"href\":\"/\",\"children\":[\"$\",\"$L4\",null,{\"className\":\"absolute -top-[31px]\",\"src\":\"/logo250x135.gif\",\"priority\":true,\"alt\":\"Home\",\"width\":250,\"height\":135}]}],[\"$\",\"div\",null,{\"className\":\"w-[calc(100%-300px)] translate-x-[300px] translate-y-[2px] h-[90px] relative overflow-hidden\",\"children\":[\"$\",\"$L5\",null,{\"adUnit\":\"/67541884/CPLeader728\",\"adSlotId\":\"div-gpt-ad-1738591571151-0\",\"adSize\":[728,90],\"className\":\"absolute top-0 left-0\"}]}]]}]}]}],[\"$\",\"$L6\",null,{}]]}],[\"$\",\"main\",null,{\"className\":\"px-2 py-10\",\"children\":[\"$\",\"$L7\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L8\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":[[[\"$\",\"title\",null,{\"children\":\"404: This page could not be found.\"}],[\"$\",\"div\",null,{\"style\":{\"fontFamily\":\"system-ui,\\\"Segoe UI\\\",Roboto,Helvetica,Arial,sans-serif,\\\"Apple Color Emoji\\\",\\\"Segoe UI Emoji\\\"\",\"height\":\"100vh\",\"textAlign\":\"center\",\"display\":\"flex\",\"flexDirection\":\"column\",\"alignItems\":\"center\",\"justifyContent\":\"center\"},\"children\":[\"$\",\"div\",null,{\"children\":[[\"$\",\"style\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}\"}}],[\"$\",\"h1\",null,{\"className\":\"next-error-h1\",\"style\":{\"display\":\"inline-block\",\"margin\":\"0 20px 0 0\",\"padding\":\"0 23px 0 0\",\"fontSize\":24,\"fontWeight\":500,\"verticalAlign\":\"top\",\"lineHeight\":\"49px\"},\"children\":404}],[\"$\",\"div\",null,{\"style\":{\"display\":\"inline-block\"},\"children\":[\"$\",\"h2\",null,{\"style\":{\"fontSize\":14,\"fontWeight\":400,\"lineHeight\":\"49px\",\"margin\":0},\"children\":\"This page could not be found.\"}]}]]}]}]],[]],\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]}],[\"$\",\"footer\",null,{\"className\":\"custom-container flex flex-col gap-3 px-2\",\"children\":[[\"$\",\"div\",null,{\"className\":\"mt-2 py-4 min-h-36 bg-primary\"}],[\"$\",\"div\",null,{\"className\":\"border-t-4 border-primary p-3 flex justify-between\",\"children\":[[\"$\",\"nav\",null,{\"className\":\"flex-1\",\"children\":[\"$\",\"ul\",null,{\"children\":[[\"$\",\"li\",null,{\"children\":[\"$\",\"a\",null,{\"href\":\"http://developermedia.com/\",\"rel\":\"nofollow noreferrer\",\"children\":\"Advertise\"}]}],[\"$\",\"li\",null,{\"children\":[\"$\",\"$L3\",null,{\"href\":\"/info/privacy.aspx\",\"children\":\"Privacy\"}]}],[\"$\",\"li\",null,{\"children\":[\"$\",\"$L3\",null,{\"href\":\"/info/cookie.aspx\",\"children\":\"Cookies\"}]}],[\"$\",\"li\",null,{\"children\":[\"$\",\"$L3\",null,{\"href\":\"/info/TermsOfUse.aspx\",\"children\":\"Terms of Use\"}]}]]}]}],[\"$\",\"div\",null,{\"className\":\"flex-1\"}],[\"$\",\"div\",null,{\"className\":\"flex-1 text-gray text-sm text-right\",\"children\":[\"Copyright © \",[\"$\",\"a\",null,{\"href\":\"mailto:webmaster@codeproject.com\",\"children\":\"CodeProject\"}],\", 1999-2025\",[\"$\",\"br\",null,{}],\"All Rights Reserved.\"]}]]}]]}]]}]]}]]}],{\"children\":[\"article\",[\"$\",\"$1\",\"c\",{\"children\":[null,[\"$\",\"$L7\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L8\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":\"$undefined\",\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]]}],{\"children\":[[\"articleType\",\"Articles\",\"d\"],[\"$\",\"$1\",\"c\",{\"children\":[null,[\"$\",\"$L7\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L8\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":\"$undefined\",\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]]}],{\"children\":[[\"articleId\",\"8170\",\"d\"],[\"$\",\"$1\",\"c\",{\"children\":[null,[\"$\",\"$L7\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L8\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":\"$undefined\",\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]]}],{\"children\":[[\"articleSlug\",\"Adapting-GRML\",\"d\"],[\"$\",\"$1\",\"c\",{\"children\":[null,[\"$\",\"$L7\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L8\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":\"$undefined\",\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]]}],{\"children\":[\"__PAGE__\",[\"$\",\"$1\",\"c\",{\"children\":[\"$L9\",[\"$\",\"$La\",null,{\"children\":\"$Lb\"}],null,[\"$\",\"$Lc\",null,{\"children\":[\"$Ld\",\"$Le\",[\"$\",\"$Lf\",null,{\"promise\":\"$@10\"}]]}]]}],{},null,false]},null,false]},null,false]},null,false]},null,false]},null,false],[\"$\",\"$1\",\"h\",{\"children\":[null,[\"$\",\"$1\",\"MD-3ByVa6Kzdg6xrME3vr\",{\"children\":[[\"$\",\"$L11\",null,{\"children\":\"$L12\"}],[\"$\",\"meta\",null,{\"name\":\"next-size-adjust\",\"content\":\"\"}]]}],null]}],false]],\"m\":\"$undefined\",\"G\":[\"$13\",\"$undefined\"],\"s\":false,\"S\":false}\n"])</script><script>self.__next_f.push([1,"b:[\"$\",\"$14\",null,{\"fallback\":null,\"children\":[\"$\",\"$L15\",null,{\"promise\":\"$@16\"}]}]\ne:null\n12:[[\"$\",\"meta\",\"0\",{\"charSet\":\"utf-8\"}],[\"$\",\"meta\",\"1\",{\"name\":\"viewport\",\"content\":\"width=device-width, initial-scale=1\"}]]\nd:null\n"])</script><script>self.__next_f.push([1,"16:{\"metadata\":[[\"$\",\"title\",\"0\",{\"children\":\"Adapting GRML - CodeProject\"}],[\"$\",\"link\",\"1\",{\"rel\":\"manifest\",\"href\":\"/manifest.json\",\"crossOrigin\":\"$undefined\"}]],\"error\":null,\"digest\":\"$undefined\"}\n10:{\"metadata\":\"$16:metadata\",\"error\":null,\"digest\":\"$undefined\"}\n"])</script><script>self.__next_f.push([1,"17:I[9741,[\"869\",\"static/chunks/869-095b567be01917e3.js\",\"394\",\"static/chunks/app/article/%5BarticleType%5D/%5BarticleId%5D/%5BarticleSlug%5D/page-1251365ce5bc4953.js\"],\"default\"]\n19:I[6947,[\"869\",\"static/chunks/869-095b567be01917e3.js\",\"394\",\"static/chunks/app/article/%5BarticleType%5D/%5BarticleId%5D/%5BarticleSlug%5D/page-1251365ce5bc4953.js\"],\"default\"]\n18:T706f,"])</script><script>self.__next_f.push([1,"/*\n This is the legacy article critical styles\n They are added in order to reduce mvp development time\n They should be refactored or completely replaced woth nextjs css modules in future\n*/\n\n::selection {\n background-color: #f90;\n color: #fff;\n text-shadow: none;\n}\n.blank-background {\n background-color: white;\n}\nhtml,\ndiv,\nspan,\napplet,\nobject,\niframe,\na,\nabbr,\nacronym,\nbig,\ncite,\ncode,\ndel,\ndfn,\nem,\nfont,\nimg,\nins,\nkbd,\nq,\ns,\nsamp,\nsmall,\nstrike,\nstrong,\nsub,\nsup,\ntt,\nvar,\nfieldset,\nform,\nlabel,\ntable,\ntbody,\ntfoot,\nthead,\ntr,\nth,\ntd,\nli,\nol,\nul {\n margin: 0;\n padding: 0;\n border: 0;\n}\nhtml {\n font-size: 16px;\n -webkit-font-smoothing: antialiased;\n font-smooth: always;\n}\nbody,\np,\nh1,\nh2,\nh3,\nh4,\nh5,\nh6,\nli,\ntr,\ntd,\nth,\ndd,\ndt {\n font-size: 16px;\n line-height: 1.4;\n color: #111111;\n}\nbody {\n margin: 0;\n}\nh1,\nh3,\nh4,\nh5,\nth {\n font-weight: bold;\n}\nh1 {\n color: #333333;\n padding: 0px;\n margin: 0 0 7px;\n text-align: left;\n}\nh2 {\n margin: 20px 0 11px;\n padding: 0;\n padding-bottom: 10px;\n color: #333333;\n}\nh3 {\n color: #ff9900;\n}\nh1 {\n font-size: 38px;\n font-weight: 400;\n}\nh2 {\n font-size: 29px;\n font-weight: 400;\n}\nh3 {\n font-size: 19px;\n font-weight: normal;\n}\nh4 {\n font-size: 17px;\n}\npre {\n color: black;\n background-color: #fbedbb;\n padding: 6px;\n font: 14px Consolas, monospace, mono;\n white-space: pre;\n overflow: auto;\n border: solid 1px #fbedbb;\n -moz-tab-size: 4;\n -o-tab-size: 4;\n -webkit-tab-size: 4;\n tab-size: 4;\n}\ncode {\n color: #990000;\n font: 15px Consolas, monospace, mono;\n}\ntable {\n background-color: Transparent;\n}\nimg {\n -ms-interpolation-mode: bicubic;\n}\na {\n text-decoration: none;\n color: #005782;\n}\na:visited {\n color: #800080;\n}\na:hover {\n text-decoration: underline;\n}\na:not([href]) {\n color: inherit;\n text-decoration: none;\n}\ninput[type=\"text\"],\ninput[type=\"url\"],\ninput[type=\"search\"],\ninput[type=\"email\"],\ninput[type=\"number\"],\ninput[type=\"password\"],\nselect,\ntextarea {\n border: 1px solid #d7d7d7;\n font-size: 16px;\n padding: 5px;\n}\na.button,\na.button-large,\n.button,\n.button-large {\n color: white;\n background-color: #e08900;\n border: 1px solid #cccccc;\n text-decoration: none;\n white-space: nowrap;\n font-size: 100%;\n padding: 4px;\n cursor: pointer;\n border-radius: 3px;\n -webkit-border-radius: 3px;\n -moz-border-radius: 3px;\n}\ntable.small-text td,\nul.small-text li,\nol.small-text li,\n.small-text {\n font-size: 14px;\n}\n.invisible {\n display: none;\n}\n.subdue,\n.subdue li,\ntr.subdue td {\n color: #808080;\n}\n.bold {\n font-weight: bold;\n}\n.align-left {\n text-align: left;\n}\n.align-right {\n text-align: right;\n}\n.align-center {\n text-align: center;\n}\n.float-right {\n float: right;\n}\n.float-left {\n float: left;\n}\n.sticky {\n position: sticky;\n top: 0;\n}\n.extended {\n width: 100%;\n box-sizing: border-box;\n}\n.padded-top {\n padding-top: 20px;\n}\n.tight {\n margin: 0px;\n padding: 0px;\n}\n.nowrap {\n white-space: nowrap;\n}\n.fixed-layout {\n table-layout: fixed;\n}\n.clip-text {\n text-overflow: ellipsis;\n overflow: hidden;\n white-space: nowrap;\n}\n.raised {\n background-color: #fff8df;\n border: 1px solid #cccccc;\n -moz-box-shadow: 4px 4px 16px 1px rgba(0, 0, 0, 0.25);\n -webkit-box-shadow: 4px 4px 16px 1px rgba(0, 0, 0, 0.25);\n box-shadow: 4px 4px 16px 1px rgba(0, 0, 0, 0.25);\n}\nol,\nul {\n padding-left: 40px;\n margin: 10px 0;\n}\nol.compact li,\nul.compact li,\nol li.compact,\nul li.compact {\n font-size: 14px;\n}\nul.download {\n margin-top: 25px;\n}\nul.download li,\nul li.download,\nul.Download li,\nul li.Download {\n background: url(\"/images/download24.png\") no-repeat scroll left center\n transparent;\n font-weight: bold;\n list-style-type: none;\n margin: 0px 0 6px -40px;\n padding: 0 0 1px 30px;\n vertical-align: middle;\n}\n.callout {\n margin: 20px 0;\n background-color: #ffffe1;\n color: #333333;\n border: 1px solid #cccccc;\n padding: 15px;\n border-radius: 3px;\n -webkit-border-radius: 3px;\n -moz-border-radius: 3px;\n}\n.trace {\n padding: 20px;\n background-color: #eeeeee;\n color: #333333;\n border: 1px solid red;\n font-size: 13px;\n}\ntextarea,\ninput[type=\"text\"],\ninput[type=\"button\"],\ninput[type=\"submit\"] {\n -webkit-appearance: none;\n border-radius: 0;\n}\n.container-content {\n background-color: white;\n position: relative;\n zoom: 1;\n padding: 0 9px;\n cursor: default;\n}\n.container-content-wrap {\n margin: auto;\n max-width: 1270px;\n}\n.container-content pre,\n.container-code pre,\n.answer pre {\n white-space: pre-wrap;\n /* css-3 */\n white-space: -moz-pre-wrap;\n /* Mozilla, since 1999 */\n white-space: -pre-wrap;\n /* Opera 4-6 */\n white-space: -o-pre-wrap;\n /* Opera 7 */\n word-wrap: break-word;\n /* Internet Explorer 5.5+ */\n _white-space: pre;\n /* IE only hack to re-specify in addition to word-wrap */\n word-break: break-word;\n -ms-word-break: break-word;\n}\n.flex-container {\n display: -webkit-box;\n /* OLD - iOS 6-, Safari 3.1-6 */\n display: -moz-box;\n /* OLD - Firefox 19- (buggy but mostly works) */\n display: -ms-flexbox;\n /* TWEENER - IE 10 */\n display: -webkit-flex;\n /* NEW - Chrome */\n display: flex;\n /* NEW, Spec - Opera 12.1, Firefox 20+ */\n}\n.flex-extend {\n justify-content: space-between;\n}\n.flex-wrap {\n flex-wrap: wrap;\n}\n.flex-item {\n -webkit-box-flex: 1;\n /* OLD - iOS 6-, Safari 3.1-6 */\n -moz-box-flex: 1;\n /* OLD - Firefox 19- */\n -webkit-flex: 1;\n /* Chrome */\n -ms-flex: 1;\n /* IE 10 */\n flex: 1;\n}\n.flex-item-tight {\n flex: 0 1 auto;\n}\n.hover-container {\n display: block;\n position: relative;\n}\n.clearfix:after,\n.container:after {\n display: block;\n content: \".\";\n visibility: hidden;\n height: 0px;\n clear: both;\n}\n.clearfix,\n.container {\n display: inline-block;\n /* Mac IE5 sees this */\n /* Mac IE5 comment hack \\*/\n display: block;\n /* Mac IE5 doesn't see this, but everyone else does */\n}\n.access-link,\n.access-link img {\n position: absolute;\n top: 0px;\n left: 0px;\n width: 1px;\n height: 1px;\n z-index: 101;\n border-style: none;\n margin-top: -1px;\n overflow: hidden;\n}\n.site-top-menu {\n white-space: nowrap;\n position: absolute;\n z-index: 101;\n width: 100%;\n}\n.site-top-menu .main-content {\n width: 100%;\n}\n.site-top-menu .main-content .memberbar {\n margin-left: 90px;\n margin-right: 10px;\n}\n.site-top-menu.fixed .main-content {\n margin: auto;\n max-width: 1270px;\n}\n.site-header {\n background-image: url(\"/App_Themes/CodeProject/Img/logo135-bg.gif\");\n white-space: nowrap;\n overflow: hidden;\n}\n.site-header .main-content {\n position: relative;\n overflow: hidden;\n white-space: nowrap;\n}\n.site-header .logo {\n display: inline-block;\n}\n.site-header .promo {\n display: inline-block;\n position: absolute;\n top: 33px;\n right: 0;\n}\n.site-header.fixed .main-content {\n margin: auto;\n max-width: 1270px;\n}\n.sub-headerbar {\n padding-right: 9px;\n position: relative;\n margin: auto;\n max-width: 1270px;\n}\n.sub-headerbar-divider {\n margin-left: 10px;\n height: 1px;\n border-bottom: 1px solid #cccccc;\n position: absolute;\n bottom: 2px;\n left: 0px;\n right: 9px;\n}\n.memberbar {\n height: 25px;\n padding-top: 10px;\n color: #999999;\n font-size: 14px;\n}\n.memberbar a {\n color: #808080;\n font-size: 14px;\n}\ndiv.navbar {\n white-space: nowrap;\n}\n.navmenu {\n background: white;\n color: #4d4d4d;\n padding: 0px;\n margin: 0px;\n list-style: none;\n height: 25px;\n}\n.navmenu ul,\n.navmenu li {\n margin: 0;\n padding: 0;\n}\n.navmenu .has-submenu {\n position: absolute;\n right: 5px;\n padding-left: 10px;\n}\n.navmenu \u003e li:hover \u003e a,\n.navmenu \u003e li \u003e a:active {\n border: 1px solid #cccccc;\n}\n.navmenu ul,\n.navmenu \u003e li.open:hover \u003e a,\n.navmenu \u003e li.open \u003e a:active {\n border: 1px solid #cccccc;\n border-bottom-color: white;\n}\n.navmenu \u003e li {\n margin: 0 11px 2px 2px;\n}\n.navmenu \u003e li:active,\n.navmenu \u003e li:active \u003e a,\n.navmenu \u003e li:hover,\n.navmenu \u003e li \u003e a:active {\n background: white;\n color: #4d4d4d;\n}\n.navmenu \u003e li.openable \u003e a:active,\n.navmenu \u003e li.openable:hover \u003e a {\n /*border-bottom: 1px solid @ColourBack-Menu; */\n}\n.navmenu \u003e li \u003e a {\n padding: 2px 7px 6px 7px;\n border: 1px solid transparent;\n font-weight: bold;\n}\n.navmenu a {\n display: block;\n float: left;\n color: #666666;\n background: white;\n font-size: 17px;\n padding: 0px 9px;\n text-decoration: none;\n white-space: nowrap;\n}\n.navmenu a.fly {\n white-space: nowrap;\n}\n.navmenu ul {\n background: white;\n position: absolute;\n left: -9999px;\n top: -9999px;\n list-style: none;\n}\n.navmenu li {\n float: left;\n color: #4d4d4d;\n}\n.navmenu li.last {\n height: 9px;\n}\n.navmenu li a:active,\n.navmenu li a:hover {\n color: white;\n background-color: #ff9900;\n}\n.navmenu li \u003e a:active,\n.navmenu li:hover,\n.navmenu li:hover \u003e a,\n.navmenu li:hover.heading,\n.navmenu li a.selected {\n position: relative;\n color: white;\n background-color: #ff9900;\n}\n.navmenu li.openable:hover ul {\n left: 0px;\n top: 30px;\n z-index: 500;\n}\n.navmenu li.openable:hover \u003e ul ul {\n position: absolute;\n left: -9999px;\n top: -9999px;\n width: auto;\n}\n.navmenu li ul {\n border-bottom: 5px solid #ff9900;\n}\n.navmenu li li {\n float: none;\n}\n.navmenu li li a {\n float: none;\n font-size: 16px;\n font-weight: normal;\n}\n.navmenu li li a.fly {\n color: #4d4d4d;\n background-color: white;\n padding: 2px 20px;\n}\n.navmenu li li a.break {\n margin-bottom: 15px;\n}\n.navmenu li li a.highlight1,\n.navmenu li li a.highlight1:active,\n.navmenu li li a.highlight1:hover {\n background-color: #009900;\n}\n.navmenu li li a.highlight2,\n.navmenu li li a.highlight2:active,\n.navmenu li li a.highlight2:hover {\n background-color: #ff9900;\n}\n.navmenu li li a.highlight3,\n.navmenu li li a.highlight3:active,\n.navmenu li li a.highlight3:hover {\n background-color: #000000;\n}\n.navmenu li li a.highlight1,\n.navmenu li li a.highlight2,\n.navmenu li li a.highlight3 {\n color: white;\n font-size: 16px;\n margin: 5px 0;\n padding: 9px 20px;\n}\n.site-footer {\n display: -webkit-box;\n /* OLD - iOS 6-, Safari 3.1-6 */\n display: -moz-box;\n /* OLD - Firefox 19- (buggy but mostly works) */\n display: -ms-flexbox;\n /* TWEENER - IE 10 */\n display: -webkit-flex;\n /* NEW - Chrome */\n display: flex;\n /* NEW, Spec - Opera 12.1, Firefox 20+ */\n padding-top: 5px;\n width: 100%;\n font-size: 13px;\n color: #999999;\n}\n.site-footer .align-left,\n.site-footer .align-center,\n.site-footer .align-right {\n -webkit-box-flex: 1;\n /* OLD - iOS 6-, Safari 3.1-6 */\n -moz-box-flex: 1;\n /* OLD - Firefox 19- */\n -webkit-flex: 1;\n /* Chrome */\n -ms-flex: 1;\n /* IE 10 */\n flex: 1;\n}\n.site-footer .align-left {\n flex: 1 0 100px;\n}\n.site-footer .align-center {\n flex: 0 1 0%;\n white-space: nowrap;\n}\n.site-footer .align-right {\n flex: 1 0 100px;\n}\n.site-footer .page-width .active {\n border-bottom: 2px solid #ff9900;\n}\n.searchbar {\n padding: 0;\n}\n.searchbar .search {\n margin-bottom: 4px;\n padding: 2px 5px 0px;\n border: 1px solid #cccccc;\n}\n.searchbar .search.subdue {\n color: #cccccc;\n}\n.searchbar input.search {\n width: 190px;\n border: none;\n font-size: 13px;\n padding: 4px 2px;\n}\n.searchbar .search-advanced {\n padding: 8px;\n width: 203px;\n z-index: 1000;\n background-color: white;\n border: solid 1px #cccccc;\n position: absolute;\n top: -4px;\n right: 0px;\n}\n.searchbar .popup {\n display: none;\n}\n.sub-headerbar .searchbar {\n /*\n\t.search-advanced\n\t{\n .transition(width, .1s, linear);\n\n \u0026.open\n {\n \t\twidth: 320px;\n }\n }\n */\n}\n.sub-headerbar .searchbar input.search {\n /*\n \u0026:focus,\u0026:active\n {\n position : absolute;\n top : 3px;\n right : 36px;\n height : 19px;\n border : 1px solid #ccc;\n border-right : none;\n width: 300px;\n\n .transition(width, .1s, linear);\n }\n */\n}\n.search td {\n background-color: white;\n}\n.article-container-parts {\n display: -webkit-box;\n /* OLD - iOS 6-, Safari 3.1-6 */\n display: -moz-box;\n /* OLD - Firefox 19- (buggy but mostly works) */\n display: -ms-flexbox;\n /* TWEENER - IE 10 */\n display: -webkit-flex;\n /* NEW - Chrome */\n display: flex;\n /* NEW, Spec - Opera 12.1, Firefox 20+ */\n}\n.article-container {\n -webkit-box-flex: 1;\n /* OLD - iOS 6-, Safari 3.1-6 */\n -moz-box-flex: 1;\n /* OLD - Firefox 19- */\n -webkit-flex: 1;\n /* Chrome */\n -ms-flex: 1;\n /* IE 10 */\n flex: 1;\n background-color: white;\n color: #111111;\n zoom: 1;\n position: relative;\n max-width: 100%;\n min-height: 675px;\n}\n.article-container .article {\n margin: 0 20px 0 10px;\n line-height: 143%;\n}\n.article-container span.stats {\n margin-left: 30px;\n}\n.article-left-sidebar {\n width: 120px;\n min-width: 120px;\n min-height: 400px;\n font-size: 14px;\n border-right: 1px solid #f2f2f2;\n padding: 0;\n /* Old school style */\n /*\n .license {\n font-weight: bold;\n display: inline-block;\n margin-top: 10px;\n }\n */\n}\n.article-left-sidebar .article-left-sidebar-inner {\n width: 120px;\n min-width: 120px;\n}\n.article-left-sidebar .tabs \u003e div {\n padding: 5px 0 5px 10px;\n}\n.article-left-sidebar .selected {\n font-weight: bold;\n background: transparent url(\"/images/right-selected.gif\") no-repeat scroll\n right 9px;\n}\n.article-left-sidebar h4 {\n color: #ff9900;\n font-size: 14px;\n font-weight: bold;\n}\n.article-left-sidebar .stats div div div {\n padding: 0px 0 10px 10px;\n color: #666666;\n}\n.article-right-sidebar {\n width: 300px;\n margin-left: 10px;\n font-size: 14px;\n}\n.article-right-sidebar .header {\n font-size: 22px;\n color: white;\n background-color: #ff9900;\n padding: 8px;\n font-weight: 400;\n margin: 0;\n}\n.article-right-sidebar .reading-list-toc {\n max-height: 250px;\n overflow-y: auto;\n padding-right: 6px;\n margin-top: 5px;\n}\n.article-right-sidebar .reading-list-toc .count {\n font-weight: normal;\n font-size: 13px;\n}\n.article-right-sidebar .reading-list-toc .title {\n font-size: 16px;\n}\n.article-right-sidebar .content-list-item {\n display: -webkit-box;\n /* OLD - iOS 6-, Safari 3.1-6 */\n display: -moz-box;\n /* OLD - Firefox 19- (buggy but mostly works) */\n display: -ms-flexbox;\n /* TWEENER - IE 10 */\n display: -webkit-flex;\n /* NEW - Chrome */\n display: flex;\n /* NEW, Spec - Opera 12.1, Firefox 20+ */\n justify-content: space-between;\n font-size: 14px;\n margin: 4px 0;\n}\n.article-right-sidebar .content-list-item .count {\n width: 15%;\n padding: 0px;\n}\n.article-right-sidebar .content-list-item .title {\n width: 85%;\n font-weight: normal;\n}\n.article-right-sidebar .gototop {\n text-align: center;\n padding: 10px 0;\n opacity: 0;\n -webkit-transition: opacity 0.3s linear 0ms;\n -moz-transition: opacity 0.3s linear 0ms;\n -o-transition: opacity 0.3s linear 0ms;\n transition: opacity 0.3s linear 0ms;\n}\n.container-content .edit-links {\n margin: 21px 0 0 10px;\n}\n.article-summary {\n padding: 0px 10px 0px 10px;\n overflow: hidden;\n}\n.article h1 {\n margin: 0 0 15px 0;\n}\n.article h2 {\n color: #ff9900;\n}\n.article pre {\n overflow: auto;\n}\n.article .header .title {\n color: #808080;\n}\n.article .header .author {\n font-weight: bold;\n min-width: 100px;\n}\n.article .header .author a {\n color: #808080;\n}\n.article .header .avatar {\n max-width: 48px;\n max-height: 48px;\n overflow: unset;\n}\n.article .header .avatar-wrap {\n width: 48px;\n height: 48px;\n margin-right: 10px;\n text-align: center;\n}\n.article .header .date {\n white-space: nowrap;\n}\n.article .header .license {\n margin-left: 15px;\n}\n.article .header .stats {\n margin-left: 30px;\n}\n.article img.lazyload,\n.article img.lazyloading {\n opacity: 0;\n}\n.article img {\n max-width: 700px;\n height: auto;\n}\n.article img.lazyloaded {\n opacity: 1;\n transition: opacity 300ms;\n}\n.article .summary {\n color: #808080;\n padding: 40px 0 15px 0;\n}\n.article .text {\n padding-top: 10px;\n}\n.article .reading-list-nav {\n border-top: 1px #dedede solid;\n border-bottom: 1px #dedede solid;\n padding: 10px 0;\n}\n.article .reading-list-nav .prev {\n padding-left: 20px;\n}\n.article .reading-list-nav .next {\n margin-left: 5px;\n padding-right: 20px;\n text-align: right;\n}\n.article-nav {\n text-align: right;\n margin-top: 21px;\n vertical-align: middle;\n line-height: 15px;\n}\n.msg-728x90 {\n width: 728px;\n height: 90px;\n overflow: hidden;\n}\n.msg-300x250 {\n width: 300px;\n height: 250px;\n overflow: hidden;\n}\n.content-list {\n margin-bottom: 17px;\n}\n.content-list .count {\n font-weight: bold;\n font-size: 16px;\n color: #ff9900;\n padding: 3px;\n text-align: center;\n}\n.content-list-item {\n margin: 10px 0;\n}\n.content-list-item .title {\n font-size: 14px;\n font-weight: bold;\n padding: 0px 0;\n}\n.content-list-item .title a {\n color: #005782;\n}\n.tags {\n line-height: 190%;\n}\n.tags .t {\n background: none repeat scroll 0 0 transparent;\n border: 1px solid #fbedbb;\n border-radius: 12px 0 0 12px;\n line-height: 1.4;\n padding: 0 2px 2px 3px;\n position: relative;\n text-decoration: none;\n margin: 2px 5px 4px 0;\n white-space: nowrap;\n}\n.tags .t a {\n color: #666666;\n display: inline-block;\n margin-right: 3px;\n padding-left: 5px;\n text-overflow: ellipsis;\n}\n.container-breadcrumb {\n font-size: 14px;\n margin-top: 7px;\n color: #808080;\n margin: 12px 0 35px;\n}\n.container-breadcrumb a {\n color: #808080;\n}\n.pre-lang {\n display: -webkit-box;\n /* OLD - iOS 6-, Safari 3.1-6 */\n display: -moz-box;\n /* OLD - Firefox 19- (buggy but mostly works) */\n display: -ms-flexbox;\n /* TWEENER - IE 10 */\n display: -webkit-flex;\n /* NEW - Chrome */\n display: flex;\n /* NEW, Spec - Opera 12.1, Firefox 20+ */\n background-color: #fbedbb;\n justify-content: space-between;\n padding: 4px 8px;\n margin-top: 5px;\n color: #999999;\n border-bottom: solid 1px #ffd044;\n}\n.code-comment {\n color: #008000;\n font-style: italic;\n}\n.code-keyword {\n color: Blue;\n}\n.code-sdkkeyword {\n color: #339999;\n}\n.code-string {\n color: Purple;\n}\n.code-attribute {\n color: red;\n}\n.code-leadattribute {\n color: #800000;\n}\n.pre-action-link {\n font-size: 13px;\n color: #999999;\n}\n.pre-action-link span {\n cursor: pointer;\n margin: 0;\n -webkit-transition: color 0.1s linear;\n -moz-transition: color 0.1s linear;\n -o-transition: color 0.1s linear;\n transition: color 0.1s linear;\n}\n.speech-bubble-container-down,\n.speech-bubble-container-up,\n.speech-bubble-container-up-right,\n.speech-bubble-container-left,\n.speech-bubble-container-right {\n position: relative;\n}\n.speech-bubble-up,\n.speech-bubble-down,\n.speech-bubble-left,\n.speech-bubble-right,\n.speech-bubble-up-right {\n padding: 0.6em;\n border: 1px solid #cccccc;\n background-color: white;\n margin: 15px;\n text-decoration: none;\n font-weight: normal;\n text-align: left;\n white-space: normal;\n color: #333333;\n font-size: 14px;\n line-height: 1.3;\n}\n.speech-bubble-down {\n margin-bottom: 0px;\n}\n.tooltip .speech-bubble-up,\n.tooltip .speech-bubble-up-right,\n.tooltip .speech-bubble-down,\n.tooltip .speech-bubble-left,\n.tooltip .speech-bubble-right {\n -moz-box-shadow: 4px 4px 16px 1px rgba(0, 0, 0, 0.25);\n -webkit-box-shadow: 4px 4px 16px 1px rgba(0, 0, 0, 0.25);\n box-shadow: 4px 4px 16px 1px rgba(0, 0, 0, 0.25);\n border-radius: 5px;\n -webkit-border-radius: 5px;\n -moz-border-radius: 5px;\n min-width: 75px;\n}\n.speech-bubble-pointer-down,\n.speech-bubble-pointer-down-inner {\n width: 0;\n height: 0;\n border-bottom-width: 0;\n background: none;\n}\n.speech-bubble-pointer-down {\n border-left: 7px solid transparent;\n border-right: 7px solid transparent;\n border-top: 1px solid #cccccc;\n border-top-width: 14px;\n margin-left: 35px;\n margin-bottom: 15px;\n _display: none;\n}\n.speech-bubble-pointer-up,\n.speech-bubble-pointer-up-right,\n.speech-bubble-pointer-up-inner,\n.speech-bubble-pointer-up-right-inner {\n width: 0;\n height: 0;\n border-top-width: 0;\n background: none;\n}\n.speech-bubble-pointer-up,\n.speech-bubble-pointer-up-right {\n border-left: 5px solid transparent;\n border-right: 5px solid transparent;\n border-bottom: 1px solid #cccccc;\n border-bottom-width: 14px;\n margin-left: 35px;\n position: absolute;\n top: -12px;\n _display: none;\n}\n.speech-bubble-container-up-right .speech-bubble-pointer-up-right {\n margin-left: 0;\n margin-right: 0px;\n right: 35px;\n}\n.tooltip {\n position: relative;\n text-decoration: none;\n}\n.tooltip .speech-bubble-container-up,\n.tooltip .speech-bubble-container-down,\n.tooltip .speech-bubble-container-left,\n.tooltip .speech-bubble-container-right,\n.tooltip .speech-bubble-container-up-right,\n.tooltip .tooltip-flyout {\n display: none;\n opacity: 0;\n -webkit-transition: opacity 0.5s linear 0ms;\n -moz-transition: opacity 0.5s linear 0ms;\n -o-transition: opacity 0.5s linear 0ms;\n transition: opacity 0.5s linear 0ms;\n}\n.micromodal {\n display: none;\n}\n.micromodal .modal__overlay {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n display: flex;\n justify-content: center;\n align-items: center;\n background: rgba(0, 0, 0, 0.65);\n z-index: 1000;\n}\n.micromodal .modal__container {\n box-sizing: border-box;\n overflow-y: auto;\n max-width: 500px;\n max-height: 100vh;\n padding: 30px;\n background-color: #fff;\n border-radius: 4px;\n}\n.micromodal .modal__container,\n.micromodal .modal__overlay {\n will-change: transform;\n}\n.micromodal .modal_header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 1rem;\n}\n.micromodal .modal_title {\n margin-top: 0;\n margin-bottom: 0;\n color: #ff9900;\n box-sizing: border-box;\n}\n.bottom-promo {\n height: 90px;\n margin-top: 10px;\n overflow: hidden;\n}\n.bottom-promo .msg-728x90 {\n width: 728px;\n margin: 0 auto;\n}\n.msg-728x90 {\n overflow: hidden;\n position: relative;\n height: 90px;\n min-width: 728px;\n}\ntable.forum {\n table-layout: fixed;\n margin: 0 0 20px 0;\n padding: 0px;\n width: 100%;\n}\n.forum {\n /*\n .indent\n {\n padding-left:5px; padding-right: 5px;\n }\n */\n}\n.forum table {\n border-collapse: separate;\n}\n.forum .header1,\n.forum .header1 TD {\n color: #333333;\n font-size: 14px;\n vertical-align: middle;\n}\n.forum .header2,\n.forum .header2 TD {\n color: white;\n background-color: #ff9900;\n font-size: 14px;\n vertical-align: middle;\n}\n.forum .header2 input,\n.forum .header2 TD input,\n.forum .header2 select,\n.forum .header2 TD select {\n padding: 2px;\n}\n.forum .button {\n border: 1px solid #ffcc66;\n margin: 1px;\n}\n.forum .searchbar {\n border: 1px solid #cccccc;\n padding: 4px 0 0 0;\n margin: 3px 0;\n}\n.forum .searchbar .search {\n width: 200px;\n}\n.forum .searchbar input[type=\"image\"] {\n vertical-align: middle;\n}\n.forum .dropdown {\n background-color: #fffdfa;\n font-size: 95%;\n margin-left: 5px;\n}\n.forum .footer,\n.forum .footer td,\n.forum .navbar,\n.forum .navbar td {\n font-size: 14px;\n padding: 8px 0;\n border: 0;\n border-top: 1px solid #808080;\n}\n.author-wrapper {\n position: relative;\n}\n.author-wrapper .profile-pic {\n border: 1px solid #333;\n margin: 0 13px 0 0;\n padding: 10px;\n -moz-box-shadow: 3px 3px 5px 1px rgba(0, 0, 0, 0.2);\n -webkit-box-shadow: 3px 3px 5px 1px rgba(0, 0, 0, 0.2);\n box-shadow: 3px 3px 5px 1px rgba(0, 0, 0, 0.2);\n max-height: 100px;\n}\n.author-wrapper .container-member .author {\n font-size: 29px;\n color: #333333;\n font-weight: 600;\n}\n.member-signin .forgot {\n padding: 0;\n}\n.member-signin a.forgot {\n color: #808080;\n}\n.rating-container {\n /*\n\t.rating-close\n\t{\n\t\tfont-size : @FontSize-MediumSmall;\n\t\tfont-weight : bold;\n\t\t// display : inline-block;\n\t\t// height : 19px;\n\t\tpadding : 0px 7px 3px 5px;\n\t\ttext-decoration : none;\n\t\tborder : 1px solid transparent;\n\t\tposition : absolute;\n\t\tright : 1px;\n\t\ttop : -1px;\n\n\t\t\u0026:hover { border : 1px solid @Colour-Theme1; }\n\t}*/\n}\n.rating-container .rating-prompt {\n padding-right: 5px;\n white-space: nowrap;\n line-height: 25px;\n margin-right: 2px;\n font-weight: bold;\n color: #808080;\n}\n.rating-container .rating-votes {\n margin-left: 5px;\n}\n.rating-container.large-stars,\n.rating-container.medium-stars,\n.rating-container.small-stars {\n margin-left: 7px;\n}\n.rating-container.large-stars .rating-votes,\n.rating-container.large-stars .rating-prompt,\n.rating-container.large-stars .rating-poor,\n.rating-container.large-stars .rating-good {\n line-height: 25px;\n}\n.tablet-only,\n.tablet-block-only {\n display: none;\n}\n.mobile-only,\n.mobile-block-only {\n display: none;\n}\n.desktop-only.tablet-only {\n display: inherit;\n}\n.tablet-only.desktop-only {\n display: inherit;\n}\n.rrssb-buttons,\n.rrssb-buttons li,\n.rrssb-buttons li a {\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n}\n.clearfix:after {\n clear: both;\n}\n.clearfix:before,\n.clearfix:after {\n content: \" \";\n display: table;\n}\n.rrssb-buttons {\n font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n height: 40px;\n margin: 0;\n padding: 0;\n width: 100%;\n}\n.rrssb-buttons li {\n float: left;\n height: 100%;\n list-style: none;\n margin: 0;\n padding: 0 2.5px;\n line-height: 13px;\n}\n.rrssb-buttons li.email a {\n background-color: #0a88ff;\n}\n.rrssb-buttons li.facebook a {\n background-color: #306199;\n}\n.rrssb-buttons li.linkedin a {\n background-color: #007bb6;\n}\n.rrssb-buttons li.twitter a {\n background-color: #26c4f1;\n}\n.rrssb-buttons li.reddit a {\n background-color: #8bbbe3;\n}\n.rrssb-buttons li.pinterest a {\n background-color: #b81621;\n}\n.rrssb-buttons li.compact {\n padding: 0 4.5px;\n}\n.rrssb-buttons li.compact a {\n border-radius: 50%;\n padding: 0px 7px 0 32px;\n}\n.rrssb-buttons li.compact a .icon {\n left: 7px;\n top: -3px;\n width: 5%;\n transform: scale(0.85);\n}\n.rrssb-buttons li.compact a .icon svg {\n height: auto;\n width: auto;\n}\n.rrssb-buttons li a {\n background-color: #ccc;\n border-radius: 3px;\n display: block;\n font-size: 11px;\n font-weight: bold;\n height: 100%;\n padding: 11px 7px 12px 27px;\n position: relative;\n text-align: center;\n text-decoration: none;\n text-transform: uppercase;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n width: 100%;\n -webkit-transition: background-color 0.2s ease-in-out;\n -moz-transition: background-color 0.2s ease-in-out;\n -o-transition: background-color 0.2s ease-in-out;\n transition: background-color 0.2s ease-in-out;\n}\n.rrssb-buttons li a .icon {\n display: block;\n height: 100%;\n left: 10px;\n padding-top: 9px;\n position: absolute;\n top: 0;\n width: 10%;\n}\n.rrssb-buttons li a .icon svg {\n height: 17px;\n width: 17px;\n}\n.rrssb-buttons li a .icon svg path,\n.rrssb-buttons li a .icon svg polygon {\n fill: #fff;\n}\n.cc-window {\n opacity: 1;\n background-color: #ff9900;\n /*\n -webkit-transition: opacity .25s ease;\n -moz-transition: opacity .25s ease;\n -ms-transition: opacity .25s ease;\n -o-transition: opacity .25s ease;\n transition: opacity .25s ease;\n */\n}\n.cc-window.cc-invisible {\n opacity: 0;\n}\n.cc-animate.cc-revoke {\n /*\n -webkit-transition: transform .25s ease;\n -moz-transition: transform .25s ease;\n -ms-transition: transform .25s ease;\n -o-transition: transform .25s ease;\n transition: transform .25s ease;\n */\n}\n.cc-animate.cc-revoke.cc-bottom {\n transform: translateY(2em);\n}\n.cc-window,\n.cc-revoke {\n position: fixed;\n overflow: hidden;\n box-sizing: border-box;\n /* exclude padding when dealing with width */\n font-family: \"Segoe UI\", Arial, Sans-Serif;\n font-size: 13px;\n /* by setting the base font here, we can size the rest of the popup using CSS `em` */\n line-height: 1.5em;\n display: flex;\n flex-wrap: nowrap;\n /* the following are random unjustified styles - just because - should probably be removed */\n z-index: 9999;\n}\n.cc-window.cc-banner {\n padding: 0.7em 1.8em;\n width: 100%;\n flex-direction: row;\n}\n.cc-revoke {\n padding: 0.5em;\n}\n.cc-btn,\n.cc-link,\n.cc-close,\n.cc-revoke {\n cursor: pointer;\n}\n.cc-link {\n opacity: 0.8;\n display: inline-block;\n padding: 0.2em;\n text-decoration: underline;\n}\n.cc-link:active,\n.cc-link:visited {\n color: initial;\n}\n.cc-btn {\n display: block;\n padding: 0.4em 0.8em;\n font-size: 0.9em;\n font-weight: bold;\n border-width: 2px;\n border-style: solid;\n text-align: center;\n white-space: nowrap;\n}\n.cc-banner .cc-btn:last-child {\n min-width: 110px;\n margin-left: 10px;\n}\n.cc-highlight .cc-btn:first-child {\n background-color: transparent;\n border-color: transparent;\n}\n.cc-revoke.cc-bottom {\n bottom: 0;\n left: 3em;\n border-top-left-radius: 0.5em;\n border-top-right-radius: 0.5em;\n}\n.cc-bottom {\n bottom: 1em;\n}\n.cc-window.cc-banner {\n align-items: center;\n}\n.cc-banner.cc-bottom {\n left: 0;\n right: 0;\n bottom: 0;\n}\n.cc-banner .cc-message {\n flex: 1;\n}\n.cc-compliance {\n display: flex;\n align-items: center;\n align-content: space-between;\n}\n.cc-compliance \u003e .cc-btn {\n flex: 1;\n}\n.cc-btn + .cc-btn {\n margin-left: 0.5em;\n}\n\n@keyframes showcopied {\n 0% {\n opacity: 0;\n }\n 70% {\n opacity: 1;\n }\n 100% {\n opacity: 0;\n }\n}\n"])</script><script>self.__next_f.push([1,"1a:T4925,"])</script><script>self.__next_f.push([1,"\u003cUL class=download\u003e\r\n\u003cLI\u003e\u003cA href=\"adaptingGRML/ServerScripts.zip\"\u003eDownload source code - 7.26 Kb\u003c/A\u003e \u003c/LI\u003e\u003c/UL\u003e\r\n\u003cP\u003e\u003cIMG height=372 src=\"https://cloudfront.codeproject.com/aspnet/adaptinggrml/prm1_000.jpg\" width=500\u003e\u003c/P\u003e\r\n\u003cH2\u003eIntroduction\u003c/H2\u003e\r\n\u003cP\u003eThis article introduces the process of adapting (or converting) a web page from one markup language to another. It discusses how to adapt a HTML web page to GRML. Two examples are provided. The first demonstrates how to extract hyperlinks from an HTML web page and convert it to GRML. The second demonstrates how to do this with images. These examples require server-side processing. Here, IIS, Active Server Pages (ASP), and PERL are used.\u003c/P\u003e\r\n\u003cH2\u003eBackground\u003c/H2\u003e\r\n\u003cP\u003eIt is recommended to have some experience with ASP and PERL. PERL has regular expression support that is used to extract the hyperlinks and images from the web page. Any server-side scripting environment does this, including .NET, CGI, or PHP. However, PERL and ASP are used for this article. While PERL is required, the server-side scripting language specifically used is PerlScript. To use PerlScript, download a PERL interpreter. To get one that works with IIS, try \u003cA href='http://www.activestate.com/Products/Download/Download.plex?id=\"ActivePerl\"' target=_blank\u003eActivePerl\u003c/A\u003e. If not done already, read \u003cA href=\"https://codeproject.org.cn/html/GRMLbrowser.asp\"\u003eIntroducing GRML\u003c/A\u003e and \u003cA href=\"http://grmlbrowser.com/articles/GRML_001\" target=_blank\u003eUsing GRML\u003c/A\u003e. These articles provide explanations of what GRML is and how it is used.\u003c/P\u003e\r\n\u003cH2\u003eWhat is an Adapter?\u003c/H2\u003e\r\n\u003cP\u003eAn adapter is generally defined as...\u003c/P\u003e\r\n\u003cBLOCKQUOTE\u003e\r\n\u003cP\u003ean object that converts the original interface of a component to another interface.\u003c/P\u003e\u003c/BLOCKQUOTE\u003e\r\n\u003cP\u003eFor the purposes of this article, the definition of an adapter is...\u003c/P\u003e\r\n\u003cBLOCKQUOTE\u003e\r\n\u003cP\u003eserver-side processing or scripting that converts one markup language to another.\u003c/P\u003e\u003c/BLOCKQUOTE\u003e\r\n\u003cP\u003eThis definition describes converting HTML to GRML using ASP. The adapter object is the ASP scripting, the original interface is HTML, and the other interface is GRML.\u003c/P\u003e\r\n\u003cP\u003eDepending on what is being converted, adapters need to read from the original interface and write to the other interface. In other words, an adapter needs an interface reader and an interface writer. A HTML to GRML adapter requires a HTML reader and a GRML writer.\u003c/P\u003e\r\n\u003cH2\u003eAdapting hyperlinks and images\u003c/H2\u003e\r\n\u003cP\u003eHTML does not describe many elements of its content. For example, there is no way to determine the attributes of one text block from another. However, not all HTML content is without description. It does have specific tags for hyperlinks and images.\u003c/P\u003e\r\n\u003cP\u003eUsing a specific tag to identify content makes it possible to create a script that reads only those tags. When found, the unwanted tag elements are removed, leaving only the content. The script then writes the content in the new format or markup language. This is how it adapts HTML hyperlinks or images to GRML.\u003c/P\u003e\r\n\u003cH2\u003eThe Hyperlink adapter\u003c/H2\u003e\r\n\u003cP\u003eThe use of the \u003cCODE lang=html\u003e\u003cspan class=\"code-keyword\"\u003e\u0026lt;\u003c/span\u003e\u003cspan class=\"code-leadattribute\"\u003ea\u003c/span\u003e \u003cspan class=\"code-attribute\"\u003ehref\u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=\u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e\u0026gt;\u003c/span\u003e\u003c/CODE\u003e tag allows a HTML web browser to identify which text is a hyperlink. This tag is the basis for the hyperlink adapter. It extracts all hyperlinks from an HTML web page and converts them to GRML.\u003c/P\u003e\r\n\u003cP\u003eBelow is an example of a HTML to GRML hyperlinks adapter, using PerlScript:\u003c/P\u003e\u003cPRE lang=perlscript\u003e\u003cspan class=\"code-pagedirective\"\u003e\u0026lt;%@\u003c/span\u003e\u003cspan class=\"code-leadattribute\"\u003e Language\u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=\u0026quot;\u003c/span\u003e\u003cspan class=\"code-keyword\"\u003ePerlScript%\u0026quot;\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e\u0026gt;\r\n\u0026lt;HTML\u0026gt;\r\n\u0026lt;center\u0026gt;\r\n\u0026lt;form action\u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=links.asp\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e\u0026gt;\r\nURL to extract: \u0026lt;input type\u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=text\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e name\u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=url1\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e length\u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=60\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e\u0026gt;\r\n\u0026lt;input type\u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=submit\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e\u0026gt;\r\n\u0026lt;/form\u0026gt;\r\n\u0026lt;/center\u0026gt;\r\n\u0026lt;!--\r\n\u0026lt;grml\u0026gt;\r\n\u0026lt;edit url1\u0026gt;\r\n\u0026lt;title\u0026gt;Enter URL:\u0026gt;\r\n\u0026lt;%\r\nuse HTML::LinkExtor;\r\nuse URI::URL;\r\nuse LWP;\r\n\r\nmy $url, $html;\r\n\r\n# Parsing the Request\r\n$url \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e $Request-\u0026gt;QueryString(\u0026quot;url1\u0026quot;)-\u0026gt;Item();\r\n\r\n$Response-\u0026gt;Write(\u0026quot;\u0026lt;submit\u0026gt;\\n\u0026quot;);\r\n$Response-\u0026gt;Write(\u0026quot;\u0026lt;location\u0026gt;GRMLBrowser.com/links.asp\\n\u0026quot;);\r\n$Response-\u0026gt;Write(\u0026quot;\u0026lt;/submit\u0026gt;\\n\u0026quot;);\r\n$Response-\u0026gt;Write(\u0026quot;\u0026lt;edit url1\u0026gt;\\n\u0026quot;);\r\n$Response-\u0026gt;Write(\u0026quot;\u0026lt;text\u0026gt;$url\\n\u0026quot;);\r\n$Response-\u0026gt;Write(\u0026quot;\u0026lt;/edit\u0026gt;\\n\u0026quot;);\r\n\r\nif ($url eq \u0026quot;\u0026quot;)\r\n{\r\n $Response-\u0026gt;Write(\u0026quot;\u0026lt;/GRML\u0026gt;\\n\u0026quot;);\r\n}\r\nelse\r\n{\r\n if ($url !~ /http:\\/\\//)\r\n {\r\n $url \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e= \u0026quot;\u003c/span\u003e\u003cspan class=\"code-keyword\"\u003ehttp://\u0026quot;\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e. $url;\r\n }\r\n}\r\n\r\n# Constructing the Request\r\n $_ \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e $sites;\r\n\r\n# Retrieving the Response/Resultset\r\n# - Filtering the Resultset (optional)\r\nmy $ua \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e LWP::UserAgent-\u0026gt;new(agent \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e\u0026gt; \u0026quot;Mozilla 4.0\u0026quot;);\r\nmy $request \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e HTTP::Request-\u0026gt;new('GET', $url);\r\nmy $response \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e $ua-\u0026gt;request($request);\r\n\r\nunless ($response-\u0026gt;is_success)\r\n{\r\n print $response-\u0026gt;error_as_HTML . \u0026quot;\\n\u0026quot;;\r\n exit(1);\r\n}\r\n\r\nmy $res \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e $response-\u0026gt;content(); # content without HTTP header\r\n\r\n$Response-\u0026gt;Write(\u0026quot;\u0026lt;column\u0026gt;\\n\u0026quot;);\r\n$Response-\u0026gt;Write(\u0026quot;\u0026lt;Title\u0026gt;\\n\u0026quot;);\r\n$Response-\u0026gt;Write(\u0026quot;\u0026lt;Request\u0026gt;\\n\u0026quot;);\r\n$Response-\u0026gt;Write(\u0026quot;\u0026lt;link\u0026gt;\\n\u0026quot;);\r\n$Response-\u0026gt;Write(\u0026quot;\u0026lt;/column\u0026gt;\\n\u0026quot;);\r\n\r\n$Response-\u0026gt;Write(\u0026quot;\u0026lt;result\u0026gt;\\n\u0026quot;);\r\n\r\n$res \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=~\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e s/\\n/ /gsi;\r\n\r\nwhile($res \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=~\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e m|href\u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=(.+?)\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e\u0026gt;(.*?)\u0026lt;/A\u0026gt;|gsi) ## that's all ...\r\n{\r\n my $temp_link \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e $1;\r\n my $temp_item \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e $2;\r\n \r\n $temp_link \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=~\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e s/\\'//gsi;\r\n $temp_link \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=~\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e s/\\\u0026quot;//gsi;\r\n $temp_link \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=~\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e s/ (.*)//gsi;\r\n $temp_link \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=~\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e s/\u0026lt;b\u0026gt;//gsi;\r\n $temp_link \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=~\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e s/\u0026lt;\\/b\u0026gt;//gsi;\r\n $temp_link \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=~\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e s/\u0026amp;amp;/\\\u0026amp;/gsi;\r\n $temp_link \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=~\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e s/\\n(.*)//gsi;\r\n $temp_item \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=~\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e s/\u0026lt;b\u0026gt;//gsi;\r\n $temp_item \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=~\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e s/\u0026lt;\\/b\u0026gt;//gsi;\r\n $temp_item \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=~\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e s/\u0026lt;(.+?)\u0026gt;//gsi;\r\n $temp_item \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=~\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e s/\u0026lt;\\/font\u0026gt;//gsi;\r\n $temp_item \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=~\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e s/\u0026amp;amp;/\\\u0026amp;/gsi;\r\n $temp_item \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=~\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e s/ / /gsi;\r\n $temp_item \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=~\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e s/\u0026amp;quot;/\\\u0026quot;/gsi;\r\n $temp_item \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=~\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e s/\\n(.*)//gsi;\r\n $temp_item \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=~\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e s/\\n/ /gsi;\r\n $temp_item \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=~\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e s/ (.*)//gsi;\r\n $temp_item \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=~\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e s/ (.*)//gsi;\r\n \r\n\r\n if ($temp_item !~ /img src\u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=/)\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e\r\n {\r\n if ($temp_link !~ /$url/ \u0026amp;\u0026amp; $temp_link !~ /\\/\\//)\r\n {\r\n $temp_link \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e $url . \u0026quot;\\/\u0026quot; . $temp_link;\r\n }\r\n\r\n $temp_item \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=~\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e s/\\n//gsi;\r\n $temp_link \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=~\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e s/\\n//gsi;\r\n\r\n $Response-\u0026gt;Write(\u0026quot;\u0026lt;link\u0026gt;$temp_link\\n\u0026quot;);\r\n $Response-\u0026gt;Write(\u0026quot;\u0026lt;title\u0026gt;$temp_item\\n\u0026quot;); \r\n }\r\n\r\n $Response-\u0026gt;Write(\u0026quot;\u0026lt;request\u0026gt;$url\\n\u0026quot;);\r\n $Response-\u0026gt;Write(\u0026quot;\\n\\n\u0026quot;);\r\n}\r\n\r\n$Response-\u0026gt;Write(\u0026quot;\u0026lt;/result\u0026gt;\\n\u0026quot;);\r\n$Response-\u0026gt;Write(\u0026quot;\u0026lt;/GRML\u0026gt;\\n\u0026quot;);\r\n\u003c/span\u003e\u003cspan class=\"code-pagedirective\"\u003e%\u0026gt;\u003c/span\u003e\r\n--\u0026gt;\r\n\u003cspan class=\"code-keyword\"\u003e\u0026lt;\u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e/\u003c/span\u003e\u003cspan class=\"code-leadattribute\"\u003ehtml\u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e\u0026gt;\u003c/span\u003e\u003c/PRE\u003e\r\n\u003cP\u003eWhat the above code does is it creates a form in HTML that extracts all the hyperlinks from a web page. The hyperlinks (and their titles) are formatted using GRML. To view GRML, a GRML web browser is required (such as \u003cA href=\"http://grmlbrowser.com/downloads\" target=_blank\u003ePioneer Report MDI\u003c/A\u003e).\u003c/P\u003e\r\n\u003cP\u003eAll of the server-side scripting is used as the HTML reader. Only the following lines are used as the GRML writer. They are:\u003c/P\u003e\r\n\u003cUL\u003e\r\n\u003cLI\u003e\u003cCODE lang=perlscript\u003e$Response-\u003eWrite(\"\u003ccolumn\u003e\\n\");\u003c/CODE\u003e \r\n\u003cLI\u003e\u003cCODE lang=perlscript\u003e$Response-\u003eWrite(\"\u003cTitle\u003e\\n\");\u003c/CODE\u003e \r\n\u003cLI\u003e\u003cCODE lang=perlscript\u003e$Response-\u003eWrite(\"\u003cRequest\u003e\\n\");\u003c/CODE\u003e \r\n\u003cLI\u003e\u003cCODE lang=perlscript\u003e$Response-\u003eWrite(\"\u003clink\u003e\\n\");\u003c/CODE\u003e \r\n\u003cLI\u003e\u003cCODE lang=perlscript\u003e$Response-\u003eWrite(\"\u003c/column\u003e\\n\");\u003c/CODE\u003e \r\n\u003cLI\u003e\u003cCODE lang=perlscript\u003e$Response-\u003eWrite(\"\u003cresult\u003e\\n\");\u003c/CODE\u003e \r\n\u003cLI\u003e\u003cCODE lang=perlscript\u003e$Response-\u003eWrite(\"\u003clink\u003e$temp_link\\n\");\u003c/CODE\u003e \r\n\u003cLI\u003e\u003cCODE lang=perlscript\u003e$Response-\u003eWrite(\"\u003ctitle\u003e$temp_item\\n\");\u003c/CODE\u003e \r\n\u003cLI\u003e\u003cCODE lang=perlscript\u003e$Response-\u003eWrite(\"\u003crequest\u003e$url\\n\");\u003c/CODE\u003e \r\n\u003cLI\u003e\u003cCODE lang=perlscript\u003e$Response-\u003eWrite(\"\u003c/result\u003e\\n\");\u003c/CODE\u003e \u003c/LI\u003e\u003c/UL\u003e\r\n\u003cP\u003eOnly the last three lines format the hyperlinks using GRML. The first two lines create the form in the browser window of a GRML web browser and do not use the adapted HTML hyperlinks.\u003c/P\u003e\r\n\u003cP\u003eTo see the above in action, go to \u003cA href=\"http://grmlbrowser.com/links.asp\" target=_blank\u003eHyperlink adapter\u003c/A\u003e or copy the above script to a file and host it from a local web server. Once the web page is displayed, enter a URL and press the 'Submit' button. It displays all the hyperlinks extracted from the HTML web page formatted in GRML.\u003c/P\u003e\r\n\u003cP\u003eAfter adapting hyperlinks from HTML to GRML, this is how it appears in a GRML web browser (using Pioneer Report MDI):\u003c/P\u003e\r\n\u003cP\u003e\u003cIMG height=351 src=\"https://cloudfront.codeproject.com/aspnet/adaptinggrml/prm1_001.jpg\" width=425\u003e\u003c/P\u003e\r\n\u003cH2\u003eThe Image adapter\u003c/H2\u003e\r\n\u003cP\u003eUsing the \u003cCODE lang=html\u003e\u003cspan class=\"code-keyword\"\u003e\u0026lt;\u003c/span\u003e\u003cspan class=\"code-leadattribute\"\u003eimg\u003c/span\u003e \u003cspan class=\"code-attribute\"\u003esrc\u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=\u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e\u0026gt;\u003c/span\u003e\u003c/CODE\u003e tag, a script is able to find and extract images from HTML. By reading this tag and removing unwanted tag elements, the HTML images are converted to GRML. The following script demonstrates this:\u003c/P\u003e\u003cPRE lang=perlscript\u003e\u003cspan class=\"code-pagedirective\"\u003e\u0026lt;%@\u003c/span\u003e\u003cspan class=\"code-leadattribute\"\u003e Language\u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=\u0026quot;\u003c/span\u003e\u003cspan class=\"code-keyword\"\u003ePerlScript%\u0026quot;\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e\u0026gt; \r\n\u0026lt;center\u0026gt; \r\n\u0026lt;form action\u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=translate.asp\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e\u0026gt; \r\nURL to translate: \u0026lt;input type\u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=text\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e name\u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=url1\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e length\u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=60\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e\u0026gt; \r\n\u0026lt;input type\u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=submit\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e\u0026gt; \r\n\u0026lt;/form\u0026gt; \r\n\u0026lt;/center\u0026gt; \r\n\r\n\u0026lt;!-- \r\n\u0026lt;grml\u0026gt; \r\n\u0026lt;edit url1\u0026gt; \r\n\u0026lt;title\u0026gt;Enter URL: \r\n\u0026lt;/edit\u0026gt; \r\n\r\n\u0026lt;% \r\nuse HTML::LinkExtor; \r\nuse URI::URL; \r\nuse LWP;\r\n\r\nmy $url, $html;\r\n\r\n# Parsing the Request\r\n$url \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e $Request-\u0026gt;QueryString(\u0026quot;url1\u0026quot;)-\u0026gt;Item();\r\n\r\nif ($url eq \u0026quot;\u0026quot;)\r\n{\r\n $Response-\u0026gt;Write(\u0026quot;\u0026lt;/GRML\u0026gt;\\n\u0026quot;);\r\n}\r\nelse\r\n{\r\n if ($url !~ /http:\\/\\//)\r\n {\r\n $url \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e= \u0026quot;\u003c/span\u003e\u003cspan class=\"code-keyword\"\u003ehttp://\u0026quot;\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e . $url;\r\n }\r\n}\r\n\r\n$Response-\u0026gt;Write(\u0026quot;### URL ###\\n\\n\u0026quot;);\r\n$Response-\u0026gt;Write(\u0026quot;The url is: $url\\n\\n\u0026quot;);\r\n\r\n# Constructing the Request\r\n$_ \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e $sites;\r\n\r\n# Retrieving the Response/Results\r\n# - Filtering the Results (optional)\r\nmy $ua \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e LWP::UserAgent-\u0026gt;new(agent \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e\u0026gt; \u0026quot;my agent V1.00\u0026quot;);\r\nmy $request \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e HTTP::Request-\u0026gt;new('GET', $url);\r\nmy $response \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e $ua-\u0026gt;request($request);\r\n\r\nunless ($response-\u0026gt;is_success)\r\n{\r\n print $response-\u0026gt;error_as_HTML . \u0026quot;\\n\u0026quot;;\r\n exit(1);\r\n}\r\n\r\nmy $res \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e $response-\u0026gt;content(); # content without HTTP header\r\n\r\nmy @imgs \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e ();\r\nmy @hrefs \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e ();\r\n\r\n# Make the parser. Unfortunately, we don't know the base yet\r\n# (it might be diffent from $url)\r\nmy $p \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e HTML::LinkExtor-\u0026gt;new(\\\u0026amp;callback);\r\n\r\n$p-\u0026gt;parse($res);\r\n\r\n# Expand all image URLs to absolute ones\r\nmy $base \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e $response-\u0026gt;base;\r\n\r\n@imgs \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e map { $_ \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e url($_, $base)-\u0026gt;abs; } @imgs;\r\n\r\n$Response-\u0026gt;Write(\u0026quot;\u0026lt;column\u0026gt;\\n\u0026quot;); \r\n$Response-\u0026gt;Write(\u0026quot;\u0026lt;image\u0026gt;\\n\u0026quot;); \r\n$Response-\u0026gt;Write(\u0026quot;\u0026lt;link\u0026gt;\\n\u0026quot;); \r\n$Response-\u0026gt;Write(\u0026quot;\u0026lt;/column\u0026gt;\\n\\n\u0026quot;); \r\n\r\n$Response-\u0026gt;Write(\u0026quot;\u0026lt;result\u0026gt;\\n\u0026quot;); \r\n\r\nforeach (@imgs)\r\n{\r\n $Response-\u0026gt;Write(\u0026quot;\u0026lt;image\u0026gt;$_\\n\u0026quot;);\r\n}\r\n\r\n$Response-\u0026gt;Write(\u0026quot;\\nLinks:\\n\u0026quot;);\r\n\r\nforeach (@hrefs)\r\n{\r\n my $temp \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e $_;\r\n\r\n if ($temp !~ /$url/ \u0026amp;\u0026amp; $temp !~ /\\/\\//)\r\n {\r\n $temp \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e $url . \u0026quot;\\/\u0026quot; . $temp;\r\n }\r\n\r\n $Response-\u0026gt;Write(\u0026quot;\u0026lt;link\u0026gt;$temp\\n\u0026quot;);\r\n}\r\n\r\nsub callback\r\n{\r\n my($tag, %attr) \u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e=\u003c/span\u003e\u003cspan class=\"code-attribute\"\u003e @_;\r\n\r\n push(@imgs , values %attr) if $tag eq 'img';\r\n push(@hrefs, values %attr) if $tag eq 'a';\r\n}\r\n\r\n\u003c/span\u003e\u003cspan class=\"code-pagedirective\"\u003e%\u0026gt;\u003c/span\u003e\r\n\u003cspan class=\"code-keyword\"\u003e\u0026lt;\u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e/\u003c/span\u003e\u003cspan class=\"code-leadattribute\"\u003eresult\u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e\u0026gt;\u003c/span\u003e\r\n\u003cspan class=\"code-keyword\"\u003e\u0026lt;\u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e/\u003c/span\u003e\u003cspan class=\"code-leadattribute\"\u003eGRML\u003c/span\u003e\u003cspan class=\"code-keyword\"\u003e\u0026gt;\u003c/span\u003e\r\n--\u0026gt;\u003c/PRE\u003e\r\n\u003cP\u003eThe above script is used as an HTML reader, except for the lines used to build the columns and each result. These lines are the GRML writer:\u003c/P\u003e\r\n\u003cUL\u003e\r\n\u003cLI\u003e\u003cCODE lang=perlscript\u003e$Response-\u003eWrite(\"\u003ccolumn\u003e\\n\");\u003c/CODE\u003e \r\n\u003cLI\u003e\u003cCODE lang=perlscript\u003e$Response-\u003eWrite(\"\u003cimage\u003e\\n\");\u003c/CODE\u003e \r\n\u003cLI\u003e\u003cCODE lang=perlscript\u003e$Response-\u003eWrite(\"\u003clink\u003e\\n\");\u003c/CODE\u003e \r\n\u003cLI\u003e\u003cCODE lang=perlscript\u003e$Response-\u003eWrite(\"\u003c/column\u003e\\n\\n\");\u003c/CODE\u003e \r\n\u003cLI\u003e\u003cCODE lang=perlscript\u003e$Response-\u003eWrite(\"\u003cresult\u003e\\n\");\u003c/CODE\u003e \r\n\u003cLI\u003e\u003cCODE lang=perlscript\u003e$Response-\u003eWrite(\"\u003cimage\u003e$_\\n\");\u003c/CODE\u003e \r\n\u003cLI\u003e\u003cCODE lang=perlscript\u003e$Response-\u003eWrite(\"\u003clink\u003e$temp\\n\");\u003c/CODE\u003e \r\n\u003cLI\u003e\u003cCODE lang=perlscript\u003e$Response-\u003eWrite(\"\u003c/result\u003e\\n\");\u003c/CODE\u003e \u003c/LI\u003e\u003c/UL\u003e\r\n\u003cP\u003eOnce the image content has been adapted to GRML, this is how it looks in a GRML web browser (using Pioneer Report MDI):\u003c/P\u003e\r\n\u003cP\u003e\u003cIMG height=351 src=\"https://cloudfront.codeproject.com/aspnet/adaptinggrml/prm1_002.jpg\" width=425\u003e\u003c/P\u003e\r\n\u003cH2\u003eConclusion\u003c/H2\u003e\r\n\u003cP\u003eConverting HTML to GRML is possible when using an adapter. Only the content with identifiable tags are adaptable from one markup language to another. In the case of HTML, there are tags to identify hyperlinks and images.\u003c/P\u003e\r\n\u003cP\u003eThe examples described for adapting content show how to convert HTML hyperlinks or images to GRML. The adapter consists of a HTML reader and a GRML writer. Using this adapter, a web page viewed with a HTML web browser is viewable using a GRML web browser.\u003c/P\u003e\r\n\u003cH2\u003eLatest changes\u003c/H2\u003e\r\n\u003cUL\u003e\r\n\u003cLI\u003e09/03/04 \r\n\u003cUL\u003e\r\n\u003cLI\u003eUsing GRML v1.2 in code samples. \u003c/LI\u003e\u003c/UL\u003e\r\n\u003cLI\u003e10/08/04 \r\n\u003cUL\u003e\r\n\u003cLI\u003eUsing GRML v2.3 in code samples. Pioneer Report MDI 3.64 uses GRML\u0026nbsp;v1.2 while all other GRML web browsers use v2.3. \u003c/LI\u003e\u003c/UL\u003e\u003c/LI\u003e\u003c/UL\u003e\r\n\r\n"])</script><script>self.__next_f.push([1,"9:[\"$\",\"div\",null,{\"className\":\"custom-container flex px-2 gap-8 overflow-hidden\",\"children\":[[\"$\",\"div\",null,{\"className\":\"w-[948px] max-w-full\",\"children\":[[\"$\",\"div\",null,{\"className\":\"flex gap-2 mb-2 flex-wrap\",\"children\":[[\"$\",\"a\",\"Perl\",{\"rel\":\"tag\",\"href\":\"/Tags/Perl\",\"className\":\"px-2 border border-border-yellow rounded-l-full text-gray-light visited:text-gray-light hover:underline hover:bg-yellow-light\",\"children\":\"Perl\"}],[\"$\",\"a\",\"IIS\",{\"rel\":\"tag\",\"href\":\"/Tags/IIS\",\"className\":\"px-2 border border-border-yellow rounded-l-full text-gray-light visited:text-gray-light hover:underline hover:bg-yellow-light\",\"children\":\"IIS\"}],[\"$\",\"a\",\"Windows 2003\",{\"rel\":\"tag\",\"href\":\"/Tags/Win2003\",\"className\":\"px-2 border border-border-yellow rounded-l-full text-gray-light visited:text-gray-light hover:underline hover:bg-yellow-light\",\"children\":\"Windows 2003\"}],[\"$\",\"a\",\"Windows 2000\",{\"rel\":\"tag\",\"href\":\"/Tags/Win2K\",\"className\":\"px-2 border border-border-yellow rounded-l-full text-gray-light visited:text-gray-light hover:underline hover:bg-yellow-light\",\"children\":\"Windows 2000\"}],[\"$\",\"a\",\"ASP\",{\"rel\":\"tag\",\"href\":\"/Tags/ASP\",\"className\":\"px-2 border border-border-yellow rounded-l-full text-gray-light visited:text-gray-light hover:underline hover:bg-yellow-light\",\"children\":\"ASP\"}],[\"$\",\"a\",\"Windows XP\",{\"rel\":\"tag\",\"href\":\"/Tags/WinXP\",\"className\":\"px-2 border border-border-yellow rounded-l-full text-gray-light visited:text-gray-light hover:underline hover:bg-yellow-light\",\"children\":\"Windows XP\"}],[\"$\",\"a\",\"Intermediate\",{\"rel\":\"tag\",\"href\":\"/Tags/Intermediate\",\"className\":\"px-2 border border-border-yellow rounded-l-full text-gray-light visited:text-gray-light hover:underline hover:bg-yellow-light\",\"children\":\"Intermediate\"}],[\"$\",\"a\",\"Dev\",{\"rel\":\"tag\",\"href\":\"/Tags/Dev\",\"className\":\"px-2 border border-border-yellow rounded-l-full text-gray-light visited:text-gray-light hover:underline hover:bg-yellow-light\",\"children\":\"Dev\"}],[\"$\",\"a\",\"Visual Studio\",{\"rel\":\"tag\",\"href\":\"/Tags/Visual-Studio\",\"className\":\"px-2 border border-border-yellow rounded-l-full text-gray-light visited:text-gray-light hover:underline hover:bg-yellow-light\",\"children\":\"Visual Studio\"}],[\"$\",\"a\",\"Windows\",{\"rel\":\"tag\",\"href\":\"/Tags/Windows\",\"className\":\"px-2 border border-border-yellow rounded-l-full text-gray-light visited:text-gray-light hover:underline hover:bg-yellow-light\",\"children\":\"Windows\"}],[\"$\",\"a\",\".NET\",{\"rel\":\"tag\",\"href\":\"/Tags/.NET\",\"className\":\"px-2 border border-border-yellow rounded-l-full text-gray-light visited:text-gray-light hover:underline hover:bg-yellow-light\",\"children\":\".NET\"}],[\"$\",\"a\",\"ASP.NET\",{\"rel\":\"tag\",\"href\":\"/Tags/ASP.NET\",\"className\":\"px-2 border border-border-yellow rounded-l-full text-gray-light visited:text-gray-light hover:underline hover:bg-yellow-light\",\"children\":\"ASP.NET\"}]]}],[\"$\",\"h1\",null,{\"className\":\"text-4xl text-text-gray\",\"children\":\"Adapting GRML\"}],[\"$\",\"div\",null,{\"className\":\"max-w-[600px]\",\"children\":[[\"$\",\"div\",null,{\"className\":\"flex pt-4 justify-between\",\"children\":[[\"$\",\"div\",null,{\"className\":\"text-base hover:underline font-bold\",\"children\":[\"$\",\"$L3\",null,{\"href\":\"/script/Membership/View.aspx?mid=47237\",\"className\":\"text-gray-lightest\",\"children\":\"Toby Jacob Rhodes\"}]}],[\"$\",\"div\",null,{\"className\":\"flex items-center gap-2\",\"children\":[[\"$\",\"div\",null,{\"className\":\"flex\",\"children\":[[\"$\",\"$L4\",\"0\",{\"src\":\"/icons/starIcon.png\",\"alt\":\"starIcon\",\"width\":24,\"height\":24}],[\"$\",\"div\",\"1\",{\"className\":\"relative\",\"children\":[[\"$\",\"$L4\",null,{\"src\":\"/icons/emptyStarIcon.png\",\"alt\":\"emptyStarIcon\",\"width\":24,\"height\":24}],[\"$\",\"div\",null,{\"className\":\"absolute left-0 top-0 overflow-hidden\",\"style\":{\"maxWidth\":\"54.545449999999995%\"},\"children\":[\"$\",\"$L4\",null,{\"src\":\"/icons/starIcon.png\",\"alt\":\"starIcon\",\"width\":24,\"height\":24}]}]]}],[\"$\",\"$L4\",\"2\",{\"src\":\"/icons/emptyStarIcon.png\",\"alt\":\"emptyStarIcon\",\"width\":24,\"height\":24}],[\"$\",\"$L4\",\"3\",{\"src\":\"/icons/emptyStarIcon.png\",\"alt\":\"emptyStarIcon\",\"width\":24,\"height\":24}],[\"$\",\"$L4\",\"4\",{\"src\":\"/icons/emptyStarIcon.png\",\"alt\":\"emptyStarIcon\",\"width\":24,\"height\":24}]]}],[\"$\",\"p\",null,{\"className\":\"text-sm\",\"children\":[\"1.55\",\"/5 (\",8,\" vote\",\"s\",\")\"]}]]}]]}],[\"$\",\"div\",null,{\"className\":\"flex pt-2 gap-4\",\"children\":[[\"$\",\"p\",null,{\"className\":\"text-gray-lightest text-[13px]\",\"children\":\"Sep 3, 2004\"}],null,[\"$\",\"p\",null,{\"className\":\"text-gray-lightest text-[13px]\",\"children\":[6,\" min read\"]}],[\"$\",\"div\",null,{\"className\":\"flex gap-1 items-center\",\"children\":[[\"$\",\"$L4\",null,{\"src\":\"/icons/viewsIcon.png\",\"alt\":\"viewsIcon\",\"width\":16,\"height\":16,\"className\":\"w-4 h-4\"}],[\"$\",\"p\",null,{\"className\":\"text-gray-lightest text-[13px] pl-0.5\",\"children\":98184}]]}],[\"$\",\"div\",null,{\"className\":\"flex gap-1 items-center\",\"children\":[[\"$\",\"$L4\",null,{\"src\":\"/icons/downloadIcon.png\",\"alt\":\"downloadIcon\",\"width\":16,\"height\":16,\"className\":\"w-4 h-4\"}],[\"$\",\"p\",null,{\"className\":\"text-gray-lightest text-[13px] pl-0.5\",\"children\":177}]]}]]}]]}],[\"$\",\"p\",null,{\"className\":\"pt-6 pb-4 text-gray-lightest\",\"children\":\"Convert a HTML web page to GRML.\"}],[\"$\",\"$L17\",null,{\"css\":\"$18\",\"children\":[\"$\",\"$L19\",null,{\"children\":[\"$\",\"div\",null,{\"className\":\"article\",\"dangerouslySetInnerHTML\":{\"__html\":\"$1a\"}}]}]}]]}],[\"$\",\"div\",null,{\"children\":[\"$\",\"$L5\",null,{\"adUnit\":\"/67541884/CPLargeSky160600\",\"adSlotId\":\"div-gpt-ad-1738591766860-0\",\"adSize\":[300,600],\"className\":\"mt-40 sticky top-40\"}]}]]}]\n"])</script></body></html> - 代码之家
© . All rights reserved.