diff --git a/DOM/Sources/Parser.XML.Use.swift b/DOM/Sources/Parser.XML.Use.swift index 67f0380..e8934c6 100644 --- a/DOM/Sources/Parser.XML.Use.swift +++ b/DOM/Sources/Parser.XML.Use.swift @@ -32,7 +32,17 @@ extension XMLParser { func parseUse(_ att: any AttributeParser) throws -> DOM.Use { - let use = DOM.Use(href: try att.parseUrl("xlink:href")) + let href: DOM.URL = try { + do { + return try att.parseUrl("href") + } catch XMLParser.Error.missingAttribute(_) { + /// Backward compatibility for the deprecated "xlink:href" + /// https://www.w3.org/TR/SVG/linking.html#XLinkRefAttrs + return try att.parseUrl("xlink:href") + } + }() + + let use = DOM.Use(href: href) use.x = try att.parseCoordinate("x") use.y = try att.parseCoordinate("y") diff --git a/DOM/Tests/UseTests.swift b/DOM/Tests/UseTests.swift index d1e402f..d099ce4 100644 --- a/DOM/Tests/UseTests.swift +++ b/DOM/Tests/UseTests.swift @@ -55,19 +55,38 @@ struct UseTests { @Test func use() throws { - var node = ["xlink:href": "#line2", "href": "#line1"] - - var parsed = try XMLParser().parseUse(node) - #expect(parsed.href.fragmentID == "line2") + let parsed = try XMLParser().parseUse(["href": "#line1"]) + #expect(parsed.href.fragmentID == "line1") #expect(parsed.x == nil) #expect(parsed.y == nil) - node["x"] = "20" - node["y"] = "30" + let legacyParsed = try XMLParser().parseUse([ + "xlink:href": "#line2", + "x": "20", + "y": "30" + ]) + #expect(legacyParsed.href.fragmentID == "line2") + #expect(legacyParsed.x == 20) + #expect(legacyParsed.y == 30) + } + + @Test + func usePrefersHrefWhenBothAttributesArePresent() throws { + let parsed = try XMLParser().parseUse([ + "href": "#modern", + "xlink:href": "#legacy" + ]) - parsed = try XMLParser().parseUse(node) - #expect(parsed.href.fragmentID == "line2") - #expect(parsed.x == 20) - #expect(parsed.y == 30) + #expect(parsed.href.fragmentID == "modern") + } + + @Test + func useDoesNotFallbackToXLinkHrefWhenHrefIsInvalid() { + #expect(throws: XMLParser.Error.self) { + _ = try XMLParser().parseUse([ + "href": "https://[invalid", + "xlink:href": "#legacy" + ]) + } } }