Browse Source

Add support for OPML v1 import

Frédéric Guillot 2 months ago
parent
commit
129f1bf3da
2 changed files with 76 additions and 7 deletions
  1. 5 7
      reader/opml/opml.go
  2. 71 0
      reader/opml/parser_test.go

+ 5 - 7
reader/opml/opml.go

@@ -4,7 +4,9 @@
 
 package opml // import "miniflux.app/reader/opml"
 
-import "encoding/xml"
+import (
+	"encoding/xml"
+)
 
 type opml struct {
 	XMLName  xml.Name  `xml:"opml"`
@@ -48,10 +50,6 @@ func (o *outline) GetSiteURL() string {
 	return o.FeedURL
 }
 
-func (o *outline) IsCategory() bool {
-	return o.Text != "" && o.SiteURL == "" && o.FeedURL == ""
-}
-
 func (o *outline) Append(subscriptions SubcriptionList, category string) SubcriptionList {
 	if o.FeedURL != "" {
 		subscriptions = append(subscriptions, &Subcription{
@@ -67,10 +65,10 @@ func (o *outline) Append(subscriptions SubcriptionList, category string) Subcrip
 
 func (o *opml) Transform() SubcriptionList {
 	var subscriptions SubcriptionList
-
 	for _, outline := range o.Outlines {
-		if outline.IsCategory() {
+		if len(outline.Outlines) > 0 {
 			for _, element := range outline.Outlines {
+				// outline.Text is only available in OPML v2.
 				subscriptions = element.Append(subscriptions, outline.Text)
 			}
 		} else {

+ 71 - 0
reader/opml/parser_test.go

@@ -122,6 +122,77 @@ func TestParseOpmlWithEmptyTitleAndEmptySiteURL(t *testing.T) {
 	}
 }
 
+func TestParseOpmlVersion1(t *testing.T) {
+	data := `<?xml version="1.0"?>
+	<opml version="1.0">
+		<head>
+			<title>mySubscriptions.opml</title>
+			<dateCreated>Wed, 13 Mar 2019 11:51:41 GMT</dateCreated>
+		</head>
+		<body>
+			<outline title="Feed 1">
+				<outline type="rss" title="Feed 1" xmlUrl="http://example.org/feed1/" htmlUrl="http://example.org/1"></outline>
+			</outline>
+			<outline title="Feed 2">
+				<outline type="rss" title="Feed 2" xmlUrl="http://example.org/feed2/" htmlUrl="http://example.org/2"></outline>
+			</outline>
+		</body>
+	</opml>
+	`
+
+	var expected SubcriptionList
+	expected = append(expected, &Subcription{Title: "Feed 1", FeedURL: "http://example.org/feed1/", SiteURL: "http://example.org/1", CategoryName: ""})
+	expected = append(expected, &Subcription{Title: "Feed 2", FeedURL: "http://example.org/feed2/", SiteURL: "http://example.org/2", CategoryName: ""})
+
+	subscriptions, err := Parse(bytes.NewBufferString(data))
+	if err != nil {
+		t.Error(err)
+	}
+
+	if len(subscriptions) != 2 {
+		t.Errorf("Wrong number of subscriptions: %d instead of %d", len(subscriptions), 2)
+	}
+
+	for i := 0; i < len(subscriptions); i++ {
+		if !subscriptions[i].Equals(expected[i]) {
+			t.Errorf(`Subscription are different: "%v" vs "%v"`, subscriptions[i], expected[i])
+		}
+	}
+}
+
+func TestParseOpmlVersion1WithoutOuterOutline(t *testing.T) {
+	data := `<?xml version="1.0"?>
+	<opml version="1.0">
+		<head>
+			<title>mySubscriptions.opml</title>
+			<dateCreated>Wed, 13 Mar 2019 11:51:41 GMT</dateCreated>
+		</head>
+		<body>
+			<outline type="rss" title="Feed 1" xmlUrl="http://example.org/feed1/" htmlUrl="http://example.org/1"></outline>
+			<outline type="rss" title="Feed 2" xmlUrl="http://example.org/feed2/" htmlUrl="http://example.org/2"></outline>
+		</body>
+	</opml>
+	`
+
+	var expected SubcriptionList
+	expected = append(expected, &Subcription{Title: "Feed 1", FeedURL: "http://example.org/feed1/", SiteURL: "http://example.org/1", CategoryName: ""})
+	expected = append(expected, &Subcription{Title: "Feed 2", FeedURL: "http://example.org/feed2/", SiteURL: "http://example.org/2", CategoryName: ""})
+
+	subscriptions, err := Parse(bytes.NewBufferString(data))
+	if err != nil {
+		t.Error(err)
+	}
+
+	if len(subscriptions) != 2 {
+		t.Errorf("Wrong number of subscriptions: %d instead of %d", len(subscriptions), 2)
+	}
+
+	for i := 0; i < len(subscriptions); i++ {
+		if !subscriptions[i].Equals(expected[i]) {
+			t.Errorf(`Subscription are different: "%v" vs "%v"`, subscriptions[i], expected[i])
+		}
+	}
+}
 func TestParseInvalidXML(t *testing.T) {
 	data := `garbage`
 	_, err := Parse(bytes.NewBufferString(data))