diff --git a/src/main/java/com/commafeed/backend/feeds/FeedParser.java b/src/main/java/com/commafeed/backend/feeds/FeedParser.java index 09020246..b63a748f 100644 --- a/src/main/java/com/commafeed/backend/feeds/FeedParser.java +++ b/src/main/java/com/commafeed/backend/feeds/FeedParser.java @@ -55,6 +55,7 @@ public class FeedParser { if (xmlString == null) { throw new FeedException("Input string is null for url " + feedUrl); } + xmlString = FeedUtils.replaceHtmlEntitiesWithNumericEntities(xmlString); InputSource source = new InputSource(new StringReader(xmlString)); SyndFeed rss = new SyndFeedInput().build(source); handleForeignMarkup(rss); diff --git a/src/main/java/com/commafeed/backend/feeds/FeedUtils.java b/src/main/java/com/commafeed/backend/feeds/FeedUtils.java index b3c33e9d..4ca97223 100644 --- a/src/main/java/com/commafeed/backend/feeds/FeedUtils.java +++ b/src/main/java/com/commafeed/backend/feeds/FeedUtils.java @@ -129,6 +129,14 @@ public class FeedUtils { } return encoding; } + + public static String replaceHtmlEntitiesWithNumericEntities(String source){ + String result = source; + for(String entity : HtmlEntities.NUMERIC_MAPPING.keySet()){ + result = result.replace(entity, HtmlEntities.NUMERIC_MAPPING.get(entity)); + } + return result; + } /** * Normalize the url. The resulting url is not meant to be fetched but rather used as a mean to identify a feed and avoid duplicates diff --git a/src/main/java/com/commafeed/backend/feeds/HtmlEntities.java b/src/main/java/com/commafeed/backend/feeds/HtmlEntities.java new file mode 100644 index 00000000..d8486d36 --- /dev/null +++ b/src/main/java/com/commafeed/backend/feeds/HtmlEntities.java @@ -0,0 +1,266 @@ +package com.commafeed.backend.feeds; + +import java.util.Collections; +import java.util.Map; + +import com.google.gwt.thirdparty.guava.common.collect.Maps; + +public class HtmlEntities { + public static final Map NUMERIC_MAPPING = Collections.unmodifiableMap(loadMap()); + + private static Map loadMap() { + Map map = Maps.newLinkedHashMap(); + map.put("Á", "Á"); + map.put("á", "á"); + map.put("Â", "Â"); + map.put("â", "â"); + map.put("´", "´"); + map.put("Æ", "Æ"); + map.put("æ", "æ"); + map.put("À", "À"); + map.put("à", "à"); + map.put("ℵ", "ℵ"); + map.put("Α", "Α"); + map.put("α", "α"); + map.put("&", "&"); + map.put("∧", "∧"); + map.put("∠", "∠"); + map.put("Å", "Å"); + map.put("å", "å"); + map.put("≈", "≈"); + map.put("Ã", "Ã"); + map.put("ã", "ã"); + map.put("Ä", "Ä"); + map.put("ä", "ä"); + map.put("„", "„"); + map.put("Β", "Β"); + map.put("β", "β"); + map.put("¦", "¦"); + map.put("•", "•"); + map.put("∩", "∩"); + map.put("Ç", "Ç"); + map.put("ç", "ç"); + map.put("¸", "¸"); + map.put("¢", "¢"); + map.put("Χ", "Χ"); + map.put("χ", "χ"); + map.put("ˆ", "ˆ"); + map.put("♣", "♣"); + map.put("≅", "≅"); + map.put("©", "©"); + map.put("↵", "↵"); + map.put("∪", "∪"); + map.put("¤", "¤"); + map.put("†", "†"); + map.put("‡", "‡"); + map.put("↓", "↓"); + map.put("⇓", "⇓"); + map.put("°", "°"); + map.put("Δ", "Δ"); + map.put("δ", "δ"); + map.put("♦", "♦"); + map.put("÷", "÷"); + map.put("É", "É"); + map.put("é", "é"); + map.put("Ê", "Ê"); + map.put("ê", "ê"); + map.put("È", "È"); + map.put("è", "è"); + map.put("∅", "∅"); + map.put(" ", " "); + map.put(" ", " "); + map.put("Ε", "Ε"); + map.put("ε", "ε"); + map.put("≡", "≡"); + map.put("Η", "Η"); + map.put("η", "η"); + map.put("Ð", "Ð"); + map.put("ð", "ð"); + map.put("Ë", "Ë"); + map.put("ë", "ë"); + map.put("€", "€"); + map.put("∃", "∃"); + map.put("ƒ", "ƒ"); + map.put("∀", "∀"); + map.put("½", "½"); + map.put("¼", "¼"); + map.put("¾", "¾"); + map.put("⁄", "⁄"); + map.put("Γ", "Γ"); + map.put("γ", "γ"); + map.put("≥", "≥"); + map.put("↔", "↔"); + map.put("⇔", "⇔"); + map.put("♥", "♥"); + map.put("…", "…"); + map.put("Í", "Í"); + map.put("í", "í"); + map.put("Î", "Î"); + map.put("î", "î"); + map.put("¡", "¡"); + map.put("Ì", "Ì"); + map.put("ì", "ì"); + map.put("ℑ", "ℑ"); + map.put("∞", "∞"); + map.put("∫", "∫"); + map.put("Ι", "Ι"); + map.put("ι", "ι"); + map.put("¿", "¿"); + map.put("∈", "∈"); + map.put("Ï", "Ï"); + map.put("ï", "ï"); + map.put("Κ", "Κ"); + map.put("κ", "κ"); + map.put("Λ", "Λ"); + map.put("λ", "λ"); + map.put("⟨", "〈"); + map.put("«", "«"); + map.put("←", "←"); + map.put("⇐", "⇐"); + map.put("⌈", "⌈"); + map.put("“", "“"); + map.put("≤", "≤"); + map.put("⌊", "⌊"); + map.put("∗", "∗"); + map.put("◊", "◊"); + map.put("‎", "‎"); + map.put("‹", "‹"); + map.put("‘", "‘"); + map.put("¯", "¯"); + map.put("—", "—"); + map.put("µ", "µ"); + map.put("·", "·"); + map.put("−", "−"); + map.put("Μ", "Μ"); + map.put("μ", "μ"); + map.put("∇", "∇"); + map.put(" ", " "); + map.put("–", "–"); + map.put("≠", "≠"); + map.put("∋", "∋"); + map.put("¬", "¬"); + map.put("∉", "∉"); + map.put("⊄", "⊄"); + map.put("Ñ", "Ñ"); + map.put("ñ", "ñ"); + map.put("Ν", "Ν"); + map.put("ν", "ν"); + map.put("Ó", "Ó"); + map.put("ó", "ó"); + map.put("Ô", "Ô"); + map.put("ô", "ô"); + map.put("Œ", "Œ"); + map.put("œ", "œ"); + map.put("Ò", "Ò"); + map.put("ò", "ò"); + map.put("‾", "‾"); + map.put("Ω", "Ω"); + map.put("ω", "ω"); + map.put("Ο", "Ο"); + map.put("ο", "ο"); + map.put("⊕", "⊕"); + map.put("∨", "∨"); + map.put("ª", "ª"); + map.put("º", "º"); + map.put("Ø", "Ø"); + map.put("ø", "ø"); + map.put("Õ", "Õ"); + map.put("õ", "õ"); + map.put("⊗", "⊗"); + map.put("Ö", "Ö"); + map.put("ö", "ö"); + map.put("¶", "¶"); + map.put("∂", "∂"); + map.put("‰", "‰"); + map.put("⊥", "⊥"); + map.put("Φ", "Φ"); + map.put("φ", "φ"); + map.put("Π", "Π"); + map.put("π", "π"); + map.put("ϖ", "ϖ"); + map.put("±", "±"); + map.put("£", "£"); + map.put("′", "′"); + map.put("″", "″"); + map.put("∏", "∏"); + map.put("∝", "∝"); + map.put("Ψ", "Ψ"); + map.put("ψ", "ψ"); + map.put(""", """); + map.put("√", "√"); + map.put("⟩", "〉"); + map.put("»", "»"); + map.put("→", "→"); + map.put("⇒", "⇒"); + map.put("⌉", "⌉"); + map.put("”", "”"); + map.put("ℜ", "ℜ"); + map.put("®", "®"); + map.put("⌋", "⌋"); + map.put("Ρ", "Ρ"); + map.put("ρ", "ρ"); + map.put("‏", "‏"); + map.put("›", "›"); + map.put("’", "’"); + map.put("‚", "‚"); + map.put("Š", "Š"); + map.put("š", "š"); + map.put("⋅", "⋅"); + map.put("§", "§"); + map.put("­", "­"); + map.put("Σ", "Σ"); + map.put("σ", "σ"); + map.put("ς", "ς"); + map.put("∼", "∼"); + map.put("♠", "♠"); + map.put("⊂", "⊂"); + map.put("⊆", "⊆"); + map.put("∑", "∑"); + map.put("¹", "¹"); + map.put("²", "²"); + map.put("³", "³"); + map.put("⊃", "⊃"); + map.put("⊇", "⊇"); + map.put("ß", "ß"); + map.put("Τ", "Τ"); + map.put("τ", "τ"); + map.put("∴", "∴"); + map.put("Θ", "Θ"); + map.put("θ", "θ"); + map.put("ϑ", "ϑ"); + map.put(" ", " "); + map.put("Þ", "Þ"); + map.put("þ", "þ"); + map.put("˜", "˜"); + map.put("×", "×"); + map.put("™", "™"); + map.put("Ú", "Ú"); + map.put("ú", "ú"); + map.put("↑", "↑"); + map.put("⇑", "⇑"); + map.put("Û", "Û"); + map.put("û", "û"); + map.put("Ù", "Ù"); + map.put("ù", "ù"); + map.put("¨", "¨"); + map.put("ϒ", "ϒ"); + map.put("Υ", "Υ"); + map.put("υ", "υ"); + map.put("Ü", "Ü"); + map.put("ü", "ü"); + map.put("℘", "℘"); + map.put("Ξ", "Ξ"); + map.put("ξ", "ξ"); + map.put("Ý", "Ý"); + map.put("ý", "ý"); + map.put("¥", "¥"); + map.put("ÿ", "ÿ"); + map.put("Ÿ", "Ÿ"); + map.put("Ζ", "Ζ"); + map.put("ζ", "ζ"); + map.put("‍", "‍"); + map.put("‌", "‌"); + + return map; + } +}