@@ -45,10 +45,65 @@ public GpxWebLink(Uri href)
45
45
public GpxWebLink ( Uri href , string text , string contentType )
46
46
{
47
47
Href = href ?? throw new ArgumentNullException ( nameof ( href ) ) ;
48
+ HrefString = href . OriginalString ;
48
49
Text = text ;
49
50
ContentType = contentType ;
50
51
}
51
52
53
+ /// <summary>
54
+ /// Initializes a new instance of the <see cref="GpxWebLink"/> class.
55
+ /// <para>
56
+ /// If <paramref name="hrefString"/> is never longer than 65519 characters, then favor using
57
+ /// <see cref="GpxWebLink(Uri, string, string)"/> instead of this, since <see cref="Href"/>
58
+ /// will never be <see langword="null"/> when using that constructor.
59
+ /// </para>
60
+ /// </summary>
61
+ /// <param name="hrefString">
62
+ /// The value of <see cref="HrefString"/>.
63
+ /// </param>
64
+ /// <param name="text">
65
+ /// The value of <see cref="Text"/>.
66
+ /// </param>
67
+ /// <param name="contentType">
68
+ /// The value of <see cref="ContentType"/>.
69
+ /// </param>
70
+ /// <exception cref="ArgumentNullException">
71
+ /// <paramref name="hrefString"/> is <see langword="null"/>.
72
+ /// </exception>
73
+ /// <exception cref="ArgumentException">
74
+ /// <paramref name="hrefString"/> does not look like a valid URI string.
75
+ /// </exception>
76
+ public GpxWebLink ( string hrefString , string text , string contentType )
77
+ {
78
+ switch ( Helpers . InterpretUri ( hrefString , out var bestEffortHrefUri ) )
79
+ {
80
+ case UriValidationResult . NullValue :
81
+ throw new ArgumentNullException ( nameof ( hrefString ) ) ;
82
+
83
+ case UriValidationResult . ValidSystemUri :
84
+ Href = bestEffortHrefUri ;
85
+ break ;
86
+
87
+ case UriValidationResult . ValidOverlongDataUri :
88
+ break ;
89
+
90
+ default :
91
+ throw new ArgumentException ( "does not look like a valid URI string" , nameof ( hrefString ) ) ;
92
+ }
93
+
94
+ HrefString = hrefString ;
95
+ Text = text ;
96
+ ContentType = contentType ;
97
+ }
98
+
99
+ private GpxWebLink ( string hrefString , string text , string contentType , Uri bestEffortHrefUri )
100
+ {
101
+ HrefString = hrefString ;
102
+ Text = text ;
103
+ ContentType = contentType ;
104
+ Href = bestEffortHrefUri ;
105
+ }
106
+
52
107
/// <summary>
53
108
/// Gets the text of the hyperlink.
54
109
/// </summary>
@@ -66,24 +121,33 @@ public GpxWebLink(Uri href, string text, string contentType)
66
121
public string ContentType { get ; }
67
122
68
123
/// <summary>
69
- /// Gets the URL of the hyperlink.
124
+ /// Gets the URL of the hyperlink, or <see langword="null"/> if this instance was created
125
+ /// from a valid-looking data URI whose total length exceeded 65519 characters.
70
126
/// </summary>
71
127
/// <remarks>
72
128
/// In the official XSD schema for GPX 1.1, this corresponds to the "href" attribute.
73
129
/// </remarks>
74
130
public Uri Href { get ; }
75
131
132
+ /// <summary>
133
+ /// Gets the URL of the hyperlink, as a string.
134
+ /// </summary>
135
+ /// <remarks>
136
+ /// In the official XSD schema for GPX 1.1, this corresponds to the "href" attribute.
137
+ /// </remarks>
138
+ public string HrefString { get ; }
139
+
76
140
/// <inheritdoc />
77
141
public override bool Equals ( object obj ) => obj is GpxWebLink other &&
78
142
Text == other . Text &&
79
143
ContentType == other . ContentType &&
80
- Href == other . Href ;
144
+ HrefString == other . HrefString ;
81
145
82
146
/// <inheritdoc />
83
- public override int GetHashCode ( ) => ( Href , Text , ContentType ) . GetHashCode ( ) ;
147
+ public override int GetHashCode ( ) => ( HrefString , Text , ContentType ) . GetHashCode ( ) ;
84
148
85
149
/// <inheritdoc />
86
- public override string ToString ( ) => Helpers . BuildString ( ( nameof ( Href ) , Href ) ,
150
+ public override string ToString ( ) => Helpers . BuildString ( ( nameof ( HrefString ) , HrefString ) ,
87
151
( nameof ( Text ) , Text ) ,
88
152
( nameof ( ContentType ) , ContentType ) ) ;
89
153
@@ -115,36 +179,82 @@ public override string ToString() => Helpers.BuildString((nameof(Href), Href),
115
179
116
180
/// <summary>
117
181
/// Builds a new instance of <see cref="GpxWebLink"/> as a copy of this instance, but with
118
- /// <see cref="Href"/> replaced by the given value.
182
+ /// <see cref="Href"/> and <see cref="HrefString"/> replaced by the given value.
119
183
/// </summary>
120
184
/// <param name="href">
121
- /// The new value for <see cref="Href"/>.
185
+ /// The new value for <see cref="Href"/> and <see cref="HrefString"/> .
122
186
/// </param>
123
187
/// <returns>
124
188
/// A new <see cref="GpxWebLink"/> instance that's a copy of the current instance, but
125
- /// with its <see cref="Href"/> value set to <paramref name="href"/>.
189
+ /// with its <see cref="Href"/> value set to <paramref name="href"/> and with its
190
+ /// <see cref="HrefString"/> set accordingly.
126
191
/// </returns>
127
192
/// <exception cref="ArgumentNullException">
128
193
/// <paramref name="href"/> is <see langword="null"/>.
129
194
/// </exception>
130
195
public GpxWebLink WithHref ( Uri href ) => new GpxWebLink ( href , Text , ContentType ) ;
131
196
132
- internal static GpxWebLink Load ( XElement element )
197
+ /// <summary>
198
+ /// Builds a new instance of <see cref="GpxWebLink"/> as a copy of this instance, but with
199
+ /// <see cref="HrefString"/> and <see cref="Href"/> replaced according to the given value.
200
+ /// </summary>
201
+ /// <param name="hrefString">
202
+ /// The new value for <see cref="HrefString"/> and (if possible) <see cref="Href"/>.
203
+ /// </param>
204
+ /// <returns>
205
+ /// A new <see cref="GpxWebLink"/> instance that's a copy of the current instance, but
206
+ /// with its <see cref="HrefString"/> value set to <paramref name="hrefString"/> and its
207
+ /// <see cref="Href"/> value set accordingly.
208
+ /// </returns>
209
+ /// <exception cref="ArgumentNullException">
210
+ /// <paramref name="hrefString"/> is <see langword="null"/>.
211
+ /// </exception>
212
+ /// <exception cref="ArgumentException">
213
+ /// <paramref name="hrefString"/> does not look like a valid URI string.
214
+ /// </exception>
215
+ public GpxWebLink WithHrefString ( string hrefString ) => new GpxWebLink ( hrefString , Text , ContentType ) ;
216
+
217
+ internal static GpxWebLink Load ( XElement element , bool allowOverlongDataUri )
133
218
{
134
219
if ( element is null )
135
220
{
136
221
return null ;
137
222
}
138
223
139
- return new GpxWebLink (
140
- href : Helpers . ParseUri ( element . Attribute ( "href" ) ? . Value ) ?? throw new XmlException ( "link element must have 'href' attribute" ) ,
141
- text : element . GpxElement ( "text" ) ? . Value ,
142
- contentType : element . GpxElement ( "type" ) ? . Value ) ;
224
+ string hrefString = element . Attribute ( "href" ) ? . Value ;
225
+ string text = element . GpxElement ( "text" ) ? . Value ;
226
+ string contentType = element . GpxElement ( "type" ) ? . Value ;
227
+ switch ( Helpers . InterpretUri ( hrefString , out var bestEffortHrefUri ) )
228
+ {
229
+ case UriValidationResult . NullValue :
230
+ throw new XmlException ( "link element must have 'href' attribute" ) ;
231
+
232
+ case UriValidationResult . ValidSystemUri :
233
+ return new GpxWebLink (
234
+ href : bestEffortHrefUri ,
235
+ text : text ,
236
+ contentType : contentType ) ;
237
+
238
+ case UriValidationResult . ValidOverlongDataUri :
239
+ if ( ! allowOverlongDataUri )
240
+ {
241
+ throw new XmlException ( $ "link element's 'href' attribute looks like a valid (but long) data URI. GpxWebLink.Href will be null in these cases, so to allow this, you will need to set the { nameof ( GpxReaderSettings . BuildWebLinksForVeryLongUriValues ) } flag.") ;
242
+ }
243
+
244
+ return new GpxWebLink (
245
+ hrefString : hrefString ,
246
+ text : text ,
247
+ contentType : contentType ,
248
+ bestEffortHrefUri : bestEffortHrefUri ) ;
249
+
250
+ default :
251
+ throw new XmlException ( "link element's 'href' attribute does not look like a valid URI" ) ;
252
+ }
143
253
}
144
254
145
255
void ICanWriteToXmlWriter . Save ( XmlWriter writer )
146
256
{
147
- writer . WriteAttributeString ( "href" , Href . OriginalString ) ;
257
+ writer . WriteAttributeString ( "href" , HrefString ) ;
148
258
writer . WriteOptionalGpxElementValue ( "text" , Text ) ;
149
259
writer . WriteOptionalGpxElementValue ( "type" , ContentType ) ;
150
260
}
0 commit comments