Script to remove HTML tags from String?

Hi, I've been trying to create a pop-up menu using the show menu command but it seems like it can't process text.

I have a List and the entries look like this:

<img src='" + GetFileURL("example.png") + "' /> <font color='red'>Text Example</font>

It works with Print or the ShowMenu function but not with the show menu command.

I can't change the entries text itself so I need a way to strip the HTML tags from it and then pass it to another list or maybe something else... any ideas?


Hello.

Hi, I've been trying to create a pop-up menu using the show menu [command script] but it seems like it can't process text.

That menu only displays a raw string; in other words, it doesn't translate the HTML code.

It works with Print or the ShowMenu function but not with the show menu [command script].

This is because both of these add your HTML code to the web page, where it is displayed as you would expect. (Meaning the HTML is translated when properly added to the web page.)

I can't change the entries text itself

Why not?

Where do these text entries come from?

so I need a way to strip the HTML tags from it and then pass it to another list or maybe something else... any ideas?

EDIT

This function's code has been updated once since originally posted. I forgot to do subtract start from end and then add 1, because the third parameter in Mid is for the character count from the second parameter, not the actual position of the end character in the string.

  <function name="TagStripper" parameters="str" type="string"><![CDATA[
    str = Trim(str)
    start = Instr (str, "<")
    end = Instr (str, ">")
    tag = ""
    if (start > 0 and end > 0) {
      tag = Mid (str, start, end - start + 1)
    }
    str = Replace (str, tag, "")
    start = Instr (str, "<")
    end = Instr (str, ">")
    if (start > 0 and end > 0) {
      str = TagStripper (str)
    }
    return (str)
  ]]></function>

Making up stuff to try to emulate what I am guessing you might probably have going on in your code (without really knowing very much):

// You don't need this part.
s = "<img src='" + GetFileURL("example.png") + "' /> <font color='red'>Text Example</font>"
s2 = "<img src='" + GetFileURL("example2.png") + "' /> <font color='green'>Text Example 2</font>"
s3 = "<img src='" + GetFileURL("example3.png") + "' /> <font color='blue'>Text Example 3</font>"
strings = NewStringList()
list add (strings, s)
list add (strings, s2)
list add (strings, s3)
// Now the fake environment has been created.
// The rest of the code is all that should be required (replacing "strings" in the foreach with the real list).
choices = NewStringList()
foreach (str, strings) {
  list add (choices, TagStripper(str))
}
show menu ("Whatever question?", choices, false) {
  msg (result)
}

image


PS

Use my code at your own risk!

Best case scenario: everything will work.

Worst case scenario: your computer will spontaneously combust!


EDIT

This is the test game I created to test things:

<!--Saved by Quest 5.8.7753.35184-->
<asl version="580">
  <include ref="English.aslx" />
  <include ref="Core.aslx" />
  <game name="In-room Description Example">
    <gameid>232ffbf9-b40a-44b3-88c5-5f8bed042232</gameid>
    <version>1.2</version>
    <firstpublished>2021</firstpublished>
    <appendobjectdescription />
  </game>
  <object name="room">
    <inherit name="editor_room" />
    <isroom />
    <enter type="script"><![CDATA[
      // You don't need this part.
      s = "<img src='" + GetFileURL("example.png") + "' /> <font color='red'>Text Example</font>"
      s2 = "<img src='" + GetFileURL("example2.png") + "' /> <font color='green'>Text Example 2</font>"
      s3 = "<img src='" + GetFileURL("example3.png") + "' /> <font color='blue'>Text Example 3</font>"
      strings = NewStringList()
      list add (strings, s)
      list add (strings, s2)
      list add (strings, s3)
      // Now the fake environment has been created.
      // The rest of the code is all that should be required (replacing "strings" in the foreach with the real list).
      choices = NewStringList()
      foreach (str, strings) {
        list add (choices, TagStripper(str))
      }
      show menu ("Whatever question?", choices, false) {
        msg (result)
      }
    ]]></enter>
    <description type="string"></description>
    <object name="player">
      <inherit name="editor_object" />
      <inherit name="editor_player" />
    </object>
    <object name="frob">
      <inherit name="editor_object" />
      <inroomdescription><![CDATA[{if frob.scenery: <br/>WOW! There is a {object:frob} here!}]]></inroomdescription>
      <scenery />
      <take />
    </object>
  </object>
  <function name="TagStripper" parameters="str" type="string"><![CDATA[
    str = Trim(str)
    start = Instr (str, "<")
    end = Instr (str, ">")
    tag = ""
    if (start > 0 and end > 0) {
      tag = Mid (str, start, end - start + 1)
    }
    str = Replace (str, tag, "")
    start = Instr (str, "<")
    end = Instr (str, ">")
    if (start > 0 and end > 0) {
      str = TagStripper (str)
    }
    return (str)
  ]]></function>
</asl>

Oh, and I forgot to post this bit:


Trim
https://docs.textadventures.co.uk/quest/functions/string/trim.html


Instr
https://docs.textadventures.co.uk/quest/functions/string/instr.html


Mid
https://docs.textadventures.co.uk/quest/functions/string/mid.html


Replace
https://docs.textadventures.co.uk/quest/functions/string/replace.html


NewStringList
https://docs.textadventures.co.uk/quest/functions/newstringlist.html


foreach
https://docs.textadventures.co.uk/quest/scripts/foreach.html


list add
https://docs.textadventures.co.uk/quest/scripts/list_add.html


show menu
https://docs.textadventures.co.uk/quest/scripts/show_menu.html


EDIT: Fixed a silly error in the code snippet

Use my code at your own risk!

You put Mid (str, start, end) instead of Mid (str, start, 1+end-start). The 3rd parameter to Mid is the length of the string to extract, not the end position.

However, it would be more efficient to replace:

    tag = ""
    if (start > 0 and end > 0) {
      tag = Mid (str, start, end)
    }
    str = Replace (str, tag, "")

with:

    str = Left (str, start-1) + Mid (str, end+1)

sticking the bit before the < and the bit after the > together, rather than finding the whole tag and then doing another bunch of string comparisons to remove it.

You probably also want to check for the case where there is a > before the <; which in your script would remove part of the tag, and with my modified code would duplicate the area in between them.

A more efficient version of this would be:

  <function name="TagStripper" parameters="str" type="string"><![CDATA[
    str = Trim(str)
    while (true) {
      start = Instr (str, "<") - 1
      end = Instr (start + 1, str, ">") + 1
      if (start = -1 or end = 1) {
        return (str)
      }
      str = RTrim (Left (str, start)) + " " + LTrim (Mid (str, end))
    }
  ]]></function>

I had too many tabs open, each with a different forum thread, and I failed to refresh this one before updating my function, which I found had problems after a little more testing. :)

Now, I see that I could have saved myself 10 minutes of troubleshooting had I refreshed this page first and seen mrangel's post. (hehehe)


@mrangel

I tried your version of TagStripper, and I get:

Error running script: Error compiling expression 'Instr (str, ">", start + 1) + 1': FunctionCallElement: Could find not function 'Instr(String, String, Int32)'
Error running script: Error compiling expression 'Instr (str, ">", start + 1) + 1': FunctionCallElement: Could find not function 'Instr(String, String, Int32)'
Error running script: Error compiling expression 'Instr (str, ">", start + 1) + 1': FunctionCallElement: Could find not function 'Instr(String, String, Int32)'
Error running script: Value cannot be null.Parameter name: key

I agree with every point made about my code. Even after fixing the issue with the third parameter in Mid, my code is still inefficient and only really tested with the strings I posted in the examples.

So, I want to use mrangel's, but I can't figure out what's throwing the error.


Sorry, I was expecting it to be the same as in other languages. Usually if you have one optional parameter to a function it goes at the end, but it seems Quest's Instr puts it at the beginning.

Fixed :)


Thanks a lot for the responses, this is exactly what I needed.
Sorry for not explaining properly, I couldn't find an easy way to do it with my poor English skills haha

I'm still getting an error with mrangel's version tho

Error running script: Error evaluating expression 'Instr (start + 1, str, ">") + 1': The argument 'Start' must be greater than zero.
Error running script: Error evaluating expression 'Instr (start + 1, str, ">") + 1': The argument 'Start' must be greater than zero.
Error running script: Error evaluating expression 'Instr (start + 1, str, ">") + 1': The argument 'Start' must be greater than zero.
Error running script: Value cannot be null. Parameter name: key 

Sorry, my fault for answering on my phone without checking.

  <function name="TagStripper" parameters="str" type="string"><![CDATA[
    str = Trim(str)
    while (true) {
      start = Instr (str, "<") - 1
      if (start < 0) {
        return (str)
      }
      end = Instr (start + 1, str, ">") + 1
      if (end = 1) {
        return (str)
      }
      str = RTrim (Left (str, start)) + " " + LTrim (Mid (str, end))
    }
  ]]></function>

Log in to post a reply.

Support

Forums