Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ampersand (&) results in incorrect rendering of HTML #18

Open
dangrima90 opened this issue Jun 22, 2023 · 9 comments
Open

Ampersand (&) results in incorrect rendering of HTML #18

dangrima90 opened this issue Jun 22, 2023 · 9 comments

Comments

@dangrima90
Copy link

dangrima90 commented Jun 22, 2023

If the demo apps cannot help and there is no issue for your problem, tell us about it

Demo via NS Preview: https://stackblitz.com/edit/nativescript-stackblitz-templates-ipbbwj?file=app%2Fcomponents%2FHome.vue

Which platform(s) does your issue occur on?

  • Tested on Android 12 to replicate the ampersand issue.
  • Could not test on iOS 16.5 as I was getting ReferenceError: UILabelLinkHandlerTapDelegate is not defined (not sure if it's an NS Preview issue). However when testing in the application I'm working on I saw the same behaviour.

Please, tell us how to recreate the issue in as much detail as possible.

The issue is that HTML is not rendered properly when including ampersands in the text. Example:

<HtmlLabel :html="'<h1>T&Cs</h1>'" /> <!-- this is rendered as HTML (i.e. '<h1>T&Cs</h1>') -->
<HtmlLabel :html="'<h1>T and Cs</h1>'" /> <!-- works as expected -->

I've tried using HTML Entities instead of the & symbol on its own but it resulted in the same thing.

<HtmlLabel :html="'<h1>T&amp;Cs</h1>'" /> <!-- this is rendered as HTML (i.e. '<h1>T&Cs</h1>') -->

I've included other examples in the NS Preview link above.

@farfromrefug
Copy link
Member

@dangrima90 i dont understand your issue. What you describe seems ok to me.
Please clarify what you see and what you expect

@dangrima90
Copy link
Author

dangrima90 commented Jun 22, 2023

@farfromrefug maybe I did not explain myself properly. The issue is that when having an & in the text HTML is not rendered as expected.

Code:

<HtmlLabel :html="`<h1>T&Cs</h1>`" linkColor="blue" />
<HtmlLabel :html="`<h1>T&amp;Cs</h1>`" linkColor="blue" />
<HtmlLabel :html="`<h1>T and Cs</h1>`" linkColor="blue" />
<HtmlLabel :html="`<span>T&Cs</span>`" linkColor="blue" />
<HtmlLabel :html="`<span>T&amp;Cs</span>`" linkColor="blue" />
<HtmlLabel :html="`<span>T and Cs</span>`" linkColor="blue" />
<HtmlLabel
  :html="`<a href='https://www.google.com'>T&Cs</a>`"
  linkColor="blue"
/>
<HtmlLabel
  :html="`<a href='https://www.google.com'>T&amp;Cs</a>`"
  linkColor="blue"
/>
<HtmlLabel
  :html="`<a href='https://www.google.com'>T and Cs</a>`"
  linkColor="blue"
/>

Screenshot:

The text you see highlighted with the red box appear as raw HTML rather than rendered as HTML.

@farfromrefug
Copy link
Member

@dangrima90 i get it now thanks!

@dangrima90
Copy link
Author

Hi @farfromrefug any updates on this please?

@farfromrefug
Copy link
Member

@dangrima90 no sorry it is not on my priority list right now as it can for now be fixed with a text replace.
if you want to make a a PR to fix the right way that would be welcome

@dangrima90
Copy link
Author

dangrima90 commented Jul 18, 2023

@farfromrefug I've tested this out with the repo's demo and I can verify the following:

  1. The issue is only replicable on Android
  2. From my tests it seems that &, < and &nbsp; break the rendering
  3. Changing the above to &amp;, &lt; and (space) does result in correct rendering

To test I've extracted all the characters listed here (https://www.freeformatter.com/html-entities.html) and tested them out in the Base.vue file.

Code Snippet
<script lang="ts">
import * as frameModule from '@nativescript/core/ui/frame';
import Vue from 'vue';

export const title = 'ListView sample';

function getRandomColor() {
    var letters = '0123456789ABCDEF';
    var color = '#';
    for (var i = 0; i < 6; i++) {
        color += letters[Math.floor(Math.random() * 16)];
    }
    return color;
}

export default Vue.extend({
    data() {
        return {
            title: title,
            item: null,
            items: [
                { color: getRandomColor(), text: '!' },
                { color: getRandomColor(), text: '#' },
                { color: getRandomColor(), text: '$' },
                { color: getRandomColor(), text: '%' },
                { color: getRandomColor(), text: '&' },
                { color: getRandomColor(), text: "'" },
                { color: getRandomColor(), text: '(' },
                { color: getRandomColor(), text: ')' },
                { color: getRandomColor(), text: '*' },
                { color: getRandomColor(), text: '+' },
                { color: getRandomColor(), text: ',' },
                { color: getRandomColor(), text: '-' },
                { color: getRandomColor(), text: '.' },
                { color: getRandomColor(), text: '/' },
                { color: getRandomColor(), text: '0' },
                { color: getRandomColor(), text: '1' },
                { color: getRandomColor(), text: '2' },
                { color: getRandomColor(), text: '3' },
                { color: getRandomColor(), text: '4' },
                { color: getRandomColor(), text: '5' },
                { color: getRandomColor(), text: '6' },
                { color: getRandomColor(), text: '7' },
                { color: getRandomColor(), text: '8' },
                { color: getRandomColor(), text: '9' },
                { color: getRandomColor(), text: ':' },
                { color: getRandomColor(), text: ';' },
                { color: getRandomColor(), text: '<' },
                { color: getRandomColor(), text: '=' },
                { color: getRandomColor(), text: '>' },
                { color: getRandomColor(), text: '?' },
                { color: getRandomColor(), text: '@' },
                { color: getRandomColor(), text: 'A' },
                { color: getRandomColor(), text: 'B' },
                { color: getRandomColor(), text: 'C' },
                { color: getRandomColor(), text: 'D' },
                { color: getRandomColor(), text: 'E' },
                { color: getRandomColor(), text: 'F' },
                { color: getRandomColor(), text: 'G' },
                { color: getRandomColor(), text: 'H' },
                { color: getRandomColor(), text: 'I' },
                { color: getRandomColor(), text: 'J' },
                { color: getRandomColor(), text: 'K' },
                { color: getRandomColor(), text: 'L' },
                { color: getRandomColor(), text: 'M' },
                { color: getRandomColor(), text: 'N' },
                { color: getRandomColor(), text: 'O' },
                { color: getRandomColor(), text: 'P' },
                { color: getRandomColor(), text: 'Q' },
                { color: getRandomColor(), text: 'R' },
                { color: getRandomColor(), text: 'S' },
                { color: getRandomColor(), text: 'T' },
                { color: getRandomColor(), text: 'U' },
                { color: getRandomColor(), text: 'V' },
                { color: getRandomColor(), text: 'W' },
                { color: getRandomColor(), text: 'X' },
                { color: getRandomColor(), text: 'Y' },
                { color: getRandomColor(), text: 'Z' },
                { color: getRandomColor(), text: '[' },
                { color: getRandomColor(), text: '\\\\' },
                { color: getRandomColor(), text: ']' },
                { color: getRandomColor(), text: '^' },
                { color: getRandomColor(), text: '_' },
                { color: getRandomColor(), text: '`' },
                { color: getRandomColor(), text: 'a' },
                { color: getRandomColor(), text: 'b' },
                { color: getRandomColor(), text: 'c' },
                { color: getRandomColor(), text: 'd' },
                { color: getRandomColor(), text: 'e' },
                { color: getRandomColor(), text: 'f' },
                { color: getRandomColor(), text: 'g' },
                { color: getRandomColor(), text: 'h' },
                { color: getRandomColor(), text: 'i' },
                { color: getRandomColor(), text: 'j' },
                { color: getRandomColor(), text: 'k' },
                { color: getRandomColor(), text: 'l' },
                { color: getRandomColor(), text: 'm' },
                { color: getRandomColor(), text: 'n' },
                { color: getRandomColor(), text: 'o' },
                { color: getRandomColor(), text: 'p' },
                { color: getRandomColor(), text: 'q' },
                { color: getRandomColor(), text: 'r' },
                { color: getRandomColor(), text: 's' },
                { color: getRandomColor(), text: 't' },
                { color: getRandomColor(), text: 'u' },
                { color: getRandomColor(), text: 'v' },
                { color: getRandomColor(), text: 'w' },
                { color: getRandomColor(), text: 'x' },
                { color: getRandomColor(), text: 'y' },
                { color: getRandomColor(), text: 'z' },
                { color: getRandomColor(), text: '{' },
                { color: getRandomColor(), text: '|' },
                { color: getRandomColor(), text: '}' },
                { color: getRandomColor(), text: '~' },
                { color: getRandomColor(), text: '!' },
                { color: getRandomColor(), text: '#' },
                { color: getRandomColor(), text: '$' },
                { color: getRandomColor(), text: '%' },
                { color: getRandomColor(), text: '&' },
                { color: getRandomColor(), text: "'" },
                { color: getRandomColor(), text: '(' },
                { color: getRandomColor(), text: ')' },
                { color: getRandomColor(), text: '*' },
                { color: getRandomColor(), text: '+' },
                { color: getRandomColor(), text: ',' },
                { color: getRandomColor(), text: '-' },
                { color: getRandomColor(), text: '.' },
                { color: getRandomColor(), text: '/' },
                { color: getRandomColor(), text: '0' },
                { color: getRandomColor(), text: '1' },
                { color: getRandomColor(), text: '2' },
                { color: getRandomColor(), text: '3' },
                { color: getRandomColor(), text: '4' },
                { color: getRandomColor(), text: '5' },
                { color: getRandomColor(), text: '6' },
                { color: getRandomColor(), text: '7' },
                { color: getRandomColor(), text: '8' },
                { color: getRandomColor(), text: '9' },
                { color: getRandomColor(), text: ':' },
                { color: getRandomColor(), text: ';' },
                { color: getRandomColor(), text: '<' },
                { color: getRandomColor(), text: '=' },
                { color: getRandomColor(), text: '>' },
                { color: getRandomColor(), text: '?' },
                { color: getRandomColor(), text: '@' },
                { color: getRandomColor(), text: 'A' },
                { color: getRandomColor(), text: 'B' },
                { color: getRandomColor(), text: 'C' },
                { color: getRandomColor(), text: 'D' },
                { color: getRandomColor(), text: 'E' },
                { color: getRandomColor(), text: 'F' },
                { color: getRandomColor(), text: 'G' },
                { color: getRandomColor(), text: 'H' },
                { color: getRandomColor(), text: 'I' },
                { color: getRandomColor(), text: 'J' },
                { color: getRandomColor(), text: 'K' },
                { color: getRandomColor(), text: 'L' },
                { color: getRandomColor(), text: 'M' },
                { color: getRandomColor(), text: 'N' },
                { color: getRandomColor(), text: 'O' },
                { color: getRandomColor(), text: 'P' },
                { color: getRandomColor(), text: 'Q' },
                { color: getRandomColor(), text: 'R' },
                { color: getRandomColor(), text: 'S' },
                { color: getRandomColor(), text: 'T' },
                { color: getRandomColor(), text: 'U' },
                { color: getRandomColor(), text: 'V' },
                { color: getRandomColor(), text: 'W' },
                { color: getRandomColor(), text: 'X' },
                { color: getRandomColor(), text: 'Y' },
                { color: getRandomColor(), text: 'Z' },
                { color: getRandomColor(), text: '[' },
                { color: getRandomColor(), text: '\\\\' },
                { color: getRandomColor(), text: ']' },
                { color: getRandomColor(), text: '^' },
                { color: getRandomColor(), text: '_' },
                { color: getRandomColor(), text: '`' },
                { color: getRandomColor(), text: 'a' },
                { color: getRandomColor(), text: 'b' },
                { color: getRandomColor(), text: 'c' },
                { color: getRandomColor(), text: 'd' },
                { color: getRandomColor(), text: 'e' },
                { color: getRandomColor(), text: 'f' },
                { color: getRandomColor(), text: 'g' },
                { color: getRandomColor(), text: 'h' },
                { color: getRandomColor(), text: 'i' },
                { color: getRandomColor(), text: 'j' },
                { color: getRandomColor(), text: 'k' },
                { color: getRandomColor(), text: 'l' },
                { color: getRandomColor(), text: 'm' },
                { color: getRandomColor(), text: 'n' },
                { color: getRandomColor(), text: 'o' },
                { color: getRandomColor(), text: 'p' },
                { color: getRandomColor(), text: 'q' },
                { color: getRandomColor(), text: 'r' },
                { color: getRandomColor(), text: 's' },
                { color: getRandomColor(), text: 't' },
                { color: getRandomColor(), text: 'u' },
                { color: getRandomColor(), text: 'v' },
                { color: getRandomColor(), text: 'w' },
                { color: getRandomColor(), text: 'x' },
                { color: getRandomColor(), text: 'y' },
                { color: getRandomColor(), text: 'z' },
                { color: getRandomColor(), text: '{' },
                { color: getRandomColor(), text: '|' },
                { color: getRandomColor(), text: '}' },
                { color: getRandomColor(), text: '~' },
                { color: getRandomColor(), text: '¡' },
                { color: getRandomColor(), text: '¢' },
                { color: getRandomColor(), text: '£' },
                { color: getRandomColor(), text: '¤' },
                { color: getRandomColor(), text: '¥' },
                { color: getRandomColor(), text: '¦' },
                { color: getRandomColor(), text: '§' },
                { color: getRandomColor(), text: '¨' },
                { color: getRandomColor(), text: '©' },
                { color: getRandomColor(), text: 'ª' },
                { color: getRandomColor(), text: '«' },
                { color: getRandomColor(), text: '¬' },
                { color: getRandomColor(), text: '­' },
                { color: getRandomColor(), text: '®' },
                { color: getRandomColor(), text: '¯' },
                { color: getRandomColor(), text: '°' },
                { color: getRandomColor(), text: '±' },
                { color: getRandomColor(), text: '²' },
                { color: getRandomColor(), text: '³' },
                { color: getRandomColor(), text: '´' },
                { color: getRandomColor(), text: 'µ' },
                { color: getRandomColor(), text: '¶' },
                { color: getRandomColor(), text: '¸' },
                { color: getRandomColor(), text: '¹' },
                { color: getRandomColor(), text: 'º' },
                { color: getRandomColor(), text: '»' },
                { color: getRandomColor(), text: '¼' },
                { color: getRandomColor(), text: '½' },
                { color: getRandomColor(), text: '¾' },
                { color: getRandomColor(), text: '¿' },
                { color: getRandomColor(), text: '×' },
                { color: getRandomColor(), text: '÷' },
                { color: getRandomColor(), text: '∀' },
                { color: getRandomColor(), text: '∂' },
                { color: getRandomColor(), text: '∃' },
                { color: getRandomColor(), text: '∅' },
                { color: getRandomColor(), text: '∇' },
                { color: getRandomColor(), text: '∈' },
                { color: getRandomColor(), text: '∉' },
                { color: getRandomColor(), text: '∋' },
                { color: getRandomColor(), text: '∏' },
                { color: getRandomColor(), text: '∑' },
                { color: getRandomColor(), text: '−' },
                { color: getRandomColor(), text: '∗' },
                { color: getRandomColor(), text: '√' },
                { color: getRandomColor(), text: '∝' },
                { color: getRandomColor(), text: '∞' },
                { color: getRandomColor(), text: '∠' },
                { color: getRandomColor(), text: '∧' },
                { color: getRandomColor(), text: '∨' },
                { color: getRandomColor(), text: '∩' },
                { color: getRandomColor(), text: '∪' },
                { color: getRandomColor(), text: '∫' },
                { color: getRandomColor(), text: '∴' },
                { color: getRandomColor(), text: '∼' },
                { color: getRandomColor(), text: '≅' },
                { color: getRandomColor(), text: '≈' },
                { color: getRandomColor(), text: '≠' },
                { color: getRandomColor(), text: '≡' },
                { color: getRandomColor(), text: '≤' },
                { color: getRandomColor(), text: '≥' },
                { color: getRandomColor(), text: '⊂' },
                { color: getRandomColor(), text: '⊃' },
                { color: getRandomColor(), text: '⊄' },
                { color: getRandomColor(), text: '⊆' },
                { color: getRandomColor(), text: '⊇' },
                { color: getRandomColor(), text: '⊕' },
                { color: getRandomColor(), text: '⊗' },
                { color: getRandomColor(), text: '⊥' },
                { color: getRandomColor(), text: '⋅' },
                { color: getRandomColor(), text: 'Α' },
                { color: getRandomColor(), text: 'Β' },
                { color: getRandomColor(), text: 'Γ' },
                { color: getRandomColor(), text: 'Δ' },
                { color: getRandomColor(), text: 'Ε' },
                { color: getRandomColor(), text: 'Ζ' },
                { color: getRandomColor(), text: 'Η' },
                { color: getRandomColor(), text: 'Θ' },
                { color: getRandomColor(), text: 'Ι' },
                { color: getRandomColor(), text: 'Κ' },
                { color: getRandomColor(), text: 'Λ' },
                { color: getRandomColor(), text: 'Μ' },
                { color: getRandomColor(), text: 'Ν' },
                { color: getRandomColor(), text: 'Ξ' },
                { color: getRandomColor(), text: 'Ο' },
                { color: getRandomColor(), text: 'Π' },
                { color: getRandomColor(), text: 'Ρ' },
                { color: getRandomColor(), text: 'Σ' },
                { color: getRandomColor(), text: 'Τ' },
                { color: getRandomColor(), text: 'Υ' },
                { color: getRandomColor(), text: 'Φ' },
                { color: getRandomColor(), text: 'Χ' },
                { color: getRandomColor(), text: 'Ψ' },
                { color: getRandomColor(), text: 'Ω' },
                { color: getRandomColor(), text: 'α' },
                { color: getRandomColor(), text: 'β' },
                { color: getRandomColor(), text: 'γ' },
                { color: getRandomColor(), text: 'δ' },
                { color: getRandomColor(), text: 'ε' },
                { color: getRandomColor(), text: 'ζ' },
                { color: getRandomColor(), text: 'η' },
                { color: getRandomColor(), text: 'θ' },
                { color: getRandomColor(), text: 'ι' },
                { color: getRandomColor(), text: 'κ' },
                { color: getRandomColor(), text: 'λ' },
                { color: getRandomColor(), text: 'μ' },
                { color: getRandomColor(), text: 'ν' },
                { color: getRandomColor(), text: 'ξ' },
                { color: getRandomColor(), text: 'ο' },
                { color: getRandomColor(), text: 'π' },
                { color: getRandomColor(), text: 'ρ' },
                { color: getRandomColor(), text: 'ς' },
                { color: getRandomColor(), text: 'σ' },
                { color: getRandomColor(), text: 'τ' },
                { color: getRandomColor(), text: 'υ' },
                { color: getRandomColor(), text: 'φ' },
                { color: getRandomColor(), text: 'χ' },
                { color: getRandomColor(), text: 'ψ' },
                { color: getRandomColor(), text: 'ω' },
                { color: getRandomColor(), text: 'ϑ' },
                { color: getRandomColor(), text: 'ϒ' },
                { color: getRandomColor(), text: 'ϖ' },
                { color: getRandomColor(), text: 'Œ' },
                { color: getRandomColor(), text: 'œ' },
                { color: getRandomColor(), text: 'Š' },
                { color: getRandomColor(), text: 'š' },
                { color: getRandomColor(), text: 'Ÿ' },
                { color: getRandomColor(), text: 'ƒ' },
                { color: getRandomColor(), text: 'ˆ' },
                { color: getRandomColor(), text: '˜' },
                { color: getRandomColor(), text: ' ' },
                { color: getRandomColor(), text: ' ' },
                { color: getRandomColor(), text: ' ' },
                { color: getRandomColor(), text: '‌' },
                { color: getRandomColor(), text: '‍' },
                { color: getRandomColor(), text: '–' },
                { color: getRandomColor(), text: '—' },
                { color: getRandomColor(), text: '‘' },
                { color: getRandomColor(), text: '’' },
                { color: getRandomColor(), text: '‚' },
                { color: getRandomColor(), text: '“' },
                { color: getRandomColor(), text: '”' },
                { color: getRandomColor(), text: '„' },
                { color: getRandomColor(), text: '†' },
                { color: getRandomColor(), text: '‡' },
                { color: getRandomColor(), text: '•' },
                { color: getRandomColor(), text: '…' },
                { color: getRandomColor(), text: '‰' },
                { color: getRandomColor(), text: '′' },
                { color: getRandomColor(), text: '″' },
                { color: getRandomColor(), text: '‹' },
                { color: getRandomColor(), text: '›' },
                { color: getRandomColor(), text: '‾' },
                { color: getRandomColor(), text: '€' },
                { color: getRandomColor(), text: '™' },
                { color: getRandomColor(), text: '←' },
                { color: getRandomColor(), text: '↑' },
                { color: getRandomColor(), text: '→' },
                { color: getRandomColor(), text: '↓' },
                { color: getRandomColor(), text: '↔' },
                { color: getRandomColor(), text: '↵' },
                { color: getRandomColor(), text: '⌈' },
                { color: getRandomColor(), text: '⌉' },
                { color: getRandomColor(), text: '⌊' },
                { color: getRandomColor(), text: '⌋' },
                { color: getRandomColor(), text: '◊' },
                { color: getRandomColor(), text: '♠' },
                { color: getRandomColor(), text: '♣' },
                { color: getRandomColor(), text: '♥' },
                { color: getRandomColor(), text: '♦' }
            ]
        };
    },
    methods: {
        onNavigationButtonTap() {
            frameModule.topmost().goBack();
        },
        onItemTap(item) {
            console.log('onItemTap');
        }
    },
    created() {
        console.log('listView sample created');
    },
    beforeDestroy() {}
});
</script>

My small worry is that even though I tested a lot of different symbols, I don't know if there is anything else that would break the rendering. From my end in the app I can replace the breaking symbols (&, < and &nbsp;) to make sure that the app doesn't break - but of course if there's any other symbol that breaks the rendering in the app will result in "raw HTML" being displayed.

I have tried looking at the code to understand where the error might be coming from but I'm not sure. My guess is that it is linked to the logic in here: https://github.com/nativescript-community/text/blob/0cf16bfa047e15879e49ea1e3e22fb0ac57c924e/packages/text/platforms/android/java/com/nativescript/text/Font.java#L312.

The stringBuilderFromHtmlString is called to generate the string to render, which in turn calls fromHtml. I couldn't figure out which part of the code is triggering the error.

@farfromrefug
Copy link
Member

@dangrima90 thanks for investigating this. The issue clearly comes from the html parser https://github.com/nativescript-community/text/blob/0cf16bfa047e15879e49ea1e3e22fb0ac57c924e/packages/text/platforms/android/java/com/nativescript/text/HtmlToSpannedConverter.java. It is modified code based on what you can see on the web. Clearly & and < (mostly > too) breaks the parser. Not sure why though

@farfromrefug
Copy link
Member

@dangrima90 stumbled upon this today. smart-fun/XmlToJson#24
Can you try escaping the special characters <>&?

@dangrima90
Copy link
Author

dangrima90 commented Jul 20, 2023

@farfromrefug thanks for the above - I have been testing with HTML Entities names and got somewhere but not 100% a full proof solution. For some reason in ns preview using &amp; (&) still results in an issue, however using the HTML Entity number instead &#38; does work successfully. (https://stackblitz.com/edit/nativescript-stackblitz-templates-ipbbwj?file=app%2Fcomponents%2FHome.vue). Locally I didn't see any difference between HTML Entity names (&amp;) or numbers (&#38;) using the ui-label demo.

For my use case I've been trying to use a regex to handle the replacing of these characters. The idea was to simply find &, < and > and convert them to their HTML Entity equivalent. With simple strings this will work but when dealing with nested HTML elements things start to get weird 😄 because you end up replacing the < / > of the tags themselves which will obviously break things. So I'm sure that the best thing to use is an HTML Parser.

Similar to the stackoverflow post in the issue you linked above, I found a similar explanation re: XML invalid characters: https://stackoverflow.com/a/28152666. Long story short it mentions that &, <, >, ', " between tags should be escaped. Now from my tests only & and < resulted in an error, but I guess if there's a fix to be made it would make sense to cater for all characters that should be escaped in XML.

My question would be this: Not sure if it would be possible that whilst building the HTML string (https://github.com/nativescript-community/text/blob/0cf16bfa047e15879e49ea1e3e22fb0ac57c924e/packages/text/platforms/android/java/com/nativescript/text/HtmlToSpannedConverter.java) it would check for any characters that should be escaped and it would handle that accordingly.

Just an educated guess here, maybe something like the following will cater for this issue?

@Override
public void characters(char ch[], int start, int length) throws SAXException {
    StringBuilder sb = new StringBuilder();
    /*
        * Ignore whitespace that immediately follows other whitespace; newlines count
        * as spaces.
        */
    for (int i = 0; i < length; i++) {
        char c = ch[i + start];
        if (c == ' ' || c == '\n') {
            char pred;
            int len = sb.length();
            if (len == 0) {
                len = mSpannableStringBuilder.length();
                if (len == 0) {
                    pred = '\n';
                } else {
                    pred = mSpannableStringBuilder.charAt(len - 1);
                }
            } else {
                pred = sb.charAt(len - 1);
            }
            if (pred != ' ' && pred != '\n') {
                sb.append(' ');
            }
        } else {
            switch(c) {
                case "&":
                    sb.append("&#38;");
                    break;
                case "<":
                    sb.append("&#60;");
                    break;
                case ">":
                    sb.append("&#62;");
                    break;
                case "'":
                    sb.append("&#8217;");
                    break;
                case "\"":
                    sb.append("&#34;");
                    break;
                default:
                    sb.append(c);
                    break;
            }
        }
    }
    mSpannableStringBuilder.append(sb);
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants