Repository: mmcdole/gofeed (go)

Issue:
Resolving distributed identifiers (DIDs) fails when in a "uri" attribute
Running into issues parsing this feed:

```
https://podnews.net/rss
```

What I expected: the feed to parse.

What happened: 

```
parse "at://did:plc:pzznkrzajsaqev3ffamg3jnr/app.bsky.feed.post/3ljkhwqun7l2b": invalid port ":pzznkrzajsaqev3ffamg3jnr" after host
```

Discussion:

It looks like the fix is relatively simple, and am happy to submit a PR just wanted to check if the following sounds right.

* [resolveAttrs](https://github.com/mmcdole/gofeed/blob/1a928bdf4a47574b3828b772ec4b805d5d7fc39f/internal/shared/xmlbase.go#L83) sees an attr called `uri`
*  because this attr name matches a known list of attr names, it calls `XmlBaseResolveUrl` , which does some additional work to resolve relative links, with the attribute value
*  `XmlBaseResolveUrl` treats the value as a URL, and returns an error
*  The [subsequent err check](https://github.com/mmcdole/gofeed/blob/1a928bdf4a47574b3828b772ec4b805d5d7fc39f/internal/shared/xmlbase.go#L88) returns an error and halts processing

For URIs that are not URLs, the attribute value is valid, it just doesn't carry a payload that needs resolving.

So I think it's safe to mod the code block to resolve if it can but otherwise not err out in this case.

```golang
		if uriAttrs[lowerName] {
			absURL, err := XmlBaseResolveUrl(p.BaseStack.Top(), attr.Value)
			if err != nil && absURL != nil {
				p.Attrs[i].Value = absURL.String()
			}
		}
```

Pull request description:
Fix parsing failure with non-HTTP URI schemes
Continue processing when URI attribute resolution fails instead of halting the entire feed parse. This allows feeds containing AT Protocol URIs, mailto: links, and other non-HTTP schemes to parse successfully.

Fixes #236

Patch:
diff --git a/internal/shared/xmlbase.go b/internal/shared/xmlbase.go
index 1100202..915bb82 100644
--- a/internal/shared/xmlbase.go
+++ b/internal/shared/xmlbase.go
@@ -85,12 +85,10 @@ func resolveAttrs(p *xpp.XMLPullParser) error {
 		lowerName := strings.ToLower(attr.Name.Local)
 		if uriAttrs[lowerName] {
 			absURL, err := XmlBaseResolveUrl(p.BaseStack.Top(), attr.Value)
-			if err != nil {
-				return err
-			}
-			if absURL != nil {
+			if err == nil && absURL != nil {
 				p.Attrs[i].Value = absURL.String()
 			}
+			// Continue processing even if URL resolution fails (e.g., for non-HTTP URIs like at://)
 		}
 	}
 	return nil


Test patch:
diff --git a/testdata/parser/rss/rss_channel_item_uri_at_protocol.json b/testdata/parser/rss/rss_channel_item_uri_at_protocol.json
new file mode 100644
index 0000000..3ab54f8
--- /dev/null
+++ b/testdata/parser/rss/rss_channel_item_uri_at_protocol.json
@@ -0,0 +1,19 @@
+{
+    "title": "Test Feed",
+    "link": "http://example.com",
+    "links": [
+        "http://example.com"
+    ],
+    "description": "Test Description",
+    "items": [
+        {
+            "title": "Test Item",
+            "link": "http://example.com/item",
+            "links": [
+                "http://example.com/item"
+            ],
+            "description": "Test item description"
+        }
+    ],
+    "version": "2.0"
+}
\ No newline at end of file
diff --git a/testdata/parser/rss/rss_channel_item_uri_at_protocol.xml b/testdata/parser/rss/rss_channel_item_uri_at_protocol.xml
new file mode 100644
index 0000000..6c0610d
--- /dev/null
+++ b/testdata/parser/rss/rss_channel_item_uri_at_protocol.xml
@@ -0,0 +1,15 @@
+<!--
+Description: rss item with AT Protocol URI that should not fail parsing
+-->
+<rss version="2.0">
+  <channel>
+    <title>Test Feed</title>
+    <description>Test Description</description>
+    <link>http://example.com</link>
+    <item>
+      <title>Test Item</title>
+      <description>Test item description</description>
+      <link uri="at://did:plc:pzznkrzajsaqev3ffamg3jnr/app.bsky.feed.post/3ljkhwqun7l2b">http://example.com/item</link>
+    </item>
+  </channel>
+</rss>
\ No newline at end of file