diff --git a/app/src/main/java/run/halo/feed/RssXmlBuilder.java b/app/src/main/java/run/halo/feed/RssXmlBuilder.java
index 01f714d..58d05b0 100644
--- a/app/src/main/java/run/halo/feed/RssXmlBuilder.java
+++ b/app/src/main/java/run/halo/feed/RssXmlBuilder.java
@@ -7,6 +7,7 @@
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.List;
+import java.util.Optional;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.dom4j.Document;
@@ -146,9 +147,13 @@ private void createItemElementsToChannel(Element channel, List items)
private void createItemElementToChannel(Element channel, RSS2.Item item) {
Element itemElement = channel.addElement("item");
- itemElement.addElement("title").addCDATA(item.getTitle());
+ itemElement.addElement("title")
+ .addCDATA(XmlCharUtils.removeInvalidXmlChar(item.getTitle()));
itemElement.addElement("link").addText(item.getLink());
- var description = getDescriptionWithTelemetry(item);
+
+ var description = Optional.of(getDescriptionWithTelemetry(item))
+ .map(XmlCharUtils::removeInvalidXmlChar)
+ .orElseThrow();
itemElement.addElement("description").addCDATA(description);
itemElement.addElement("guid")
.addAttribute("isPermaLink", "false")
diff --git a/app/src/test/java/run/halo/feed/RSS2Test.java b/app/src/test/java/run/halo/feed/RSS2Test.java
index a8773b1..c350485 100644
--- a/app/src/test/java/run/halo/feed/RSS2Test.java
+++ b/app/src/test/java/run/halo/feed/RSS2Test.java
@@ -4,6 +4,7 @@
import java.time.Instant;
import java.util.Arrays;
+import java.util.Collections;
import org.junit.jupiter.api.Test;
class RSS2Test {
@@ -130,4 +131,58 @@ void extractRssTagsTest() {
""".formatted(lastBuildDate);
assertThat(rssXml).isEqualToIgnoringWhitespace(expected);
}
+
+ @Test
+ void invalidCharTest() {
+ var rss = RSS2.builder()
+ .title("title")
+ .description("description")
+ .link("link")
+ .items(Collections.singletonList(
+ RSS2.Item.builder()
+ .title("title1")
+ .description("""
+ 并且会保留处理后的图片以供后面的访问。
+ """)
+ .link("link1")
+ .pubDate(Instant.EPOCH)
+ .guid("guid1")
+ .build()
+ ))
+ .build();
+ var instant = Instant.now();
+ var rssXml = new RssXmlBuilder()
+ .withRss2(rss)
+ .withGenerator("Halo")
+ .withLastBuildDate(instant)
+ .toXmlString();
+
+ var lastBuildDate = RssXmlBuilder.instantToString(instant);
+ // language=xml
+ var expected = """
+
+
+
+ title
+ link
+ description
+ Halo
+ zh-cn
+ %s
+ -
+
+
+
+ link1
+
+ 并且会保留处理后的图片以供后面的访问。
]]>
+
+ guid1
+ Thu, 1 Jan 1970 00:00:00 GMT
+
+
+
+ """.formatted(lastBuildDate);
+ assertThat(rssXml).isEqualToIgnoringWhitespace(expected);
+ }
}
\ No newline at end of file