0
# XML Processing
1
2
XML reading and writing capabilities for repository metadata files with flexible parsing options, content transformation, and proper encoding handling.
3
4
## Capabilities
5
6
### MetadataXpp3Reader
7
8
XML parser for reading repository metadata files using XPP3 pull parser with support for strict/lenient parsing and content transformation.
9
10
```java { .api }
11
/**
12
* XML reader for repository metadata files
13
* Uses XPP3 pull parser for efficient streaming XML processing
14
*/
15
public class MetadataXpp3Reader {
16
// Constructors
17
public MetadataXpp3Reader();
18
19
/**
20
* Constructor with content transformer for value interpolation during parsing
21
* @param contentTransformer - Transformer for modifying field values during XML parsing
22
*/
23
public MetadataXpp3Reader(ContentTransformer contentTransformer);
24
25
// Reading from InputStream
26
/**
27
* Read metadata from InputStream with lenient parsing (strict=false)
28
* @param input - InputStream containing XML metadata
29
* @return Metadata object parsed from XML
30
* @throws IOException - If I/O error occurs during reading
31
* @throws XmlPullParserException - If XML structure is invalid and cannot be parsed
32
*/
33
public Metadata read(InputStream input) throws IOException, XmlPullParserException;
34
35
/**
36
* Read metadata from InputStream with configurable parsing strictness
37
* @param input - InputStream containing XML metadata
38
* @param strict - true for strict validation, false for lenient best-effort parsing
39
* @return Metadata object parsed from XML
40
* @throws IOException - If I/O error occurs during reading
41
* @throws XmlPullParserException - If XML structure is invalid (strict mode) or cannot be parsed at all
42
*/
43
public Metadata read(InputStream input, boolean strict) throws IOException, XmlPullParserException;
44
45
// Reading from Reader
46
/**
47
* Read metadata from Reader with lenient parsing (strict=false)
48
* @param reader - Reader containing XML metadata
49
* @return Metadata object parsed from XML
50
* @throws IOException - If I/O error occurs during reading
51
* @throws XmlPullParserException - If XML structure is invalid and cannot be parsed
52
*/
53
public Metadata read(Reader reader) throws IOException, XmlPullParserException;
54
55
/**
56
* Read metadata from Reader with configurable parsing strictness
57
* @param reader - Reader containing XML metadata
58
* @param strict - true for strict validation, false for lenient best-effort parsing
59
* @return Metadata object parsed from XML
60
* @throws IOException - If I/O error occurs during reading
61
* @throws XmlPullParserException - If XML structure is invalid (strict mode) or cannot be parsed at all
62
*/
63
public Metadata read(Reader reader, boolean strict) throws IOException, XmlPullParserException;
64
65
// Reading from XmlPullParser
66
/**
67
* Read metadata from pre-configured XmlPullParser
68
* @param parser - XmlPullParser positioned at metadata element
69
* @param strict - true for strict validation, false for lenient best-effort parsing
70
* @return Metadata object parsed from XML
71
* @throws IOException - If I/O error occurs during reading
72
* @throws XmlPullParserException - If XML structure is invalid (strict mode) or cannot be parsed at all
73
*/
74
public Metadata read(XmlPullParser parser, boolean strict) throws IOException, XmlPullParserException;
75
76
// Configuration
77
/**
78
* Check if default XML entities are loaded during parsing
79
* @return true if default entities are loaded, false otherwise
80
*/
81
public boolean getAddDefaultEntities();
82
83
/**
84
* Configure whether to load default XML entities during parsing
85
* @param addDefaultEntities - true to load XHTML entities (lat1, special, symbol), false otherwise
86
*/
87
public void setAddDefaultEntities(boolean addDefaultEntities);
88
}
89
```
90
91
**Usage Examples:**
92
93
```java
94
import org.apache.maven.artifact.repository.metadata.Metadata;
95
import org.apache.maven.artifact.repository.metadata.io.xpp3.MetadataXpp3Reader;
96
import java.io.FileInputStream;
97
import java.io.FileReader;
98
import java.io.IOException;
99
import org.xmlpull.v1.XmlPullParserException;
100
101
// Basic reading from file
102
MetadataXpp3Reader reader = new MetadataXpp3Reader();
103
try (FileInputStream fis = new FileInputStream("repository-metadata.xml")) {
104
Metadata metadata = reader.read(fis);
105
System.out.println("GroupId: " + metadata.getGroupId());
106
System.out.println("ArtifactId: " + metadata.getArtifactId());
107
} catch (IOException | XmlPullParserException e) {
108
System.err.println("Error reading metadata: " + e.getMessage());
109
}
110
111
// Reading with strict mode (validation enabled)
112
try (FileReader fileReader = new FileReader("repository-metadata.xml")) {
113
Metadata metadata = reader.read(fileReader, true); // strict=true
114
// Strict mode will throw exceptions for invalid XML structure
115
} catch (IOException | XmlPullParserException e) {
116
System.err.println("Invalid metadata file: " + e.getMessage());
117
}
118
119
// Reading with lenient mode (best-effort parsing)
120
try (FileInputStream fis = new FileInputStream("repository-metadata.xml")) {
121
Metadata metadata = reader.read(fis, false); // strict=false
122
// Lenient mode attempts to parse even malformed XML
123
} catch (IOException | XmlPullParserException e) {
124
System.err.println("Could not parse metadata: " + e.getMessage());
125
}
126
127
// Configure default entities
128
reader.setAddDefaultEntities(true);
129
boolean hasDefaultEntities = reader.getAddDefaultEntities();
130
```
131
132
### MetadataXpp3Writer
133
134
XML writer for writing repository metadata files with proper formatting and encoding support.
135
136
```java { .api }
137
/**
138
* XML writer for repository metadata files
139
* Generates properly formatted XML with UTF-8 encoding
140
*/
141
public class MetadataXpp3Writer {
142
// Constructor
143
public MetadataXpp3Writer();
144
145
// Writing to Writer
146
/**
147
* Write metadata to Writer as formatted XML
148
* @param writer - Writer to write XML content to
149
* @param metadata - Metadata object to serialize to XML
150
* @throws IOException - If I/O error occurs during writing
151
*/
152
public void write(Writer writer, Metadata metadata) throws IOException;
153
154
// Writing to OutputStream
155
/**
156
* Write metadata to OutputStream as formatted XML with UTF-8 encoding
157
* @param output - OutputStream to write XML content to
158
* @param metadata - Metadata object to serialize to XML
159
* @throws IOException - If I/O error occurs during writing
160
*/
161
public void write(OutputStream output, Metadata metadata) throws IOException;
162
163
// Configuration
164
/**
165
* Set optional file comment to include in generated XML
166
* @param fileComment - Comment text to include at top of XML file, or null for no comment
167
*/
168
public void setFileComment(String fileComment);
169
}
170
```
171
172
**Usage Examples:**
173
174
```java
175
import org.apache.maven.artifact.repository.metadata.Metadata;
176
import org.apache.maven.artifact.repository.metadata.Versioning;
177
import org.apache.maven.artifact.repository.metadata.io.xpp3.MetadataXpp3Writer;
178
import java.io.FileOutputStream;
179
import java.io.FileWriter;
180
import java.io.IOException;
181
182
// Create metadata to write
183
Metadata metadata = new Metadata();
184
metadata.setGroupId("com.example");
185
metadata.setArtifactId("my-library");
186
187
Versioning versioning = new Versioning();
188
versioning.addVersion("1.0.0");
189
versioning.addVersion("1.1.0");
190
versioning.setLatest("1.1.0");
191
versioning.setRelease("1.1.0");
192
versioning.updateTimestamp();
193
metadata.setVersioning(versioning);
194
195
// Write to file using Writer
196
MetadataXpp3Writer writer = new MetadataXpp3Writer();
197
try (FileWriter fileWriter = new FileWriter("output-metadata.xml")) {
198
writer.write(fileWriter, metadata);
199
System.out.println("Metadata written successfully");
200
} catch (IOException e) {
201
System.err.println("Error writing metadata: " + e.getMessage());
202
}
203
204
// Write to file using OutputStream
205
try (FileOutputStream fos = new FileOutputStream("output-metadata.xml")) {
206
writer.write(fos, metadata);
207
} catch (IOException e) {
208
System.err.println("Error writing metadata: " + e.getMessage());
209
}
210
211
// Set file comment
212
writer.setFileComment("Generated by Maven Repository Metadata");
213
try (FileWriter fileWriter = new FileWriter("commented-metadata.xml")) {
214
writer.write(fileWriter, metadata);
215
}
216
```
217
218
### ContentTransformer Interface
219
220
Content transformation interface for modifying XML content during parsing, useful for preprocessing or filtering XML data.
221
222
```java { .api }
223
/**
224
* Static nested interface in MetadataXpp3Reader for transforming content during XML parsing
225
* Allows modification of field values as they are read from XML
226
*/
227
public static interface ContentTransformer {
228
/**
229
* Interpolate the value read from the xpp3 document
230
* @param source The source value
231
* @param fieldName A description of the field being interpolated
232
* @return The interpolated value
233
*/
234
String transform(String source, String fieldName);
235
}
236
```
237
238
**Usage Examples:**
239
240
```java
241
import org.apache.maven.artifact.repository.metadata.io.xpp3.MetadataXpp3Reader;
242
import org.apache.maven.artifact.repository.metadata.io.xpp3.MetadataXpp3Reader.ContentTransformer;
243
import java.io.FileInputStream;
244
245
// Create content transformer to modify version strings
246
ContentTransformer transformer = new ContentTransformer() {
247
@Override
248
public String transform(String source, String fieldName) {
249
if ("version".equals(fieldName)) {
250
// Transform version format during parsing
251
return source.replace("-SNAPSHOT", "-SNAPSHOT-CUSTOM");
252
}
253
return source; // No transformation for other fields
254
}
255
};
256
257
// Use transformer during reading
258
MetadataXpp3Reader reader = new MetadataXpp3Reader(transformer);
259
try (FileInputStream fis = new FileInputStream("repository-metadata.xml")) {
260
Metadata metadata = reader.read(fis);
261
// All version strings will have been transformed during parsing
262
} catch (Exception e) {
263
System.err.println("Error: " + e.getMessage());
264
}
265
266
// Lambda-based transformer for timestamp formatting
267
ContentTransformer timestampTransformer = (source, fieldName) -> {
268
if ("lastUpdated".equals(fieldName) && source != null) {
269
// Ensure timestamp is in correct format
270
return source.replaceAll("[^0-9]", "");
271
}
272
return source;
273
};
274
275
MetadataXpp3Reader readerWithTimestampTransform = new MetadataXpp3Reader(timestampTransformer);
276
```
277
278
### XML Processing Workflow
279
280
Complete workflow for reading, modifying, and writing repository metadata files.
281
282
**Typical Processing Pattern:**
283
284
```java
285
import org.apache.maven.artifact.repository.metadata.Metadata;
286
import org.apache.maven.artifact.repository.metadata.io.xpp3.MetadataXpp3Reader;
287
import org.apache.maven.artifact.repository.metadata.io.xpp3.MetadataXpp3Writer;
288
import java.io.*;
289
290
public class MetadataProcessor {
291
292
public void processMetadata(String inputFile, String outputFile) {
293
MetadataXpp3Reader reader = new MetadataXpp3Reader();
294
MetadataXpp3Writer writer = new MetadataXpp3Writer();
295
296
try {
297
// Read existing metadata
298
Metadata metadata;
299
try (FileInputStream fis = new FileInputStream(inputFile)) {
300
metadata = reader.read(fis, false); // lenient parsing
301
}
302
303
// Process/modify metadata
304
if (metadata.getVersioning() != null) {
305
metadata.getVersioning().updateTimestamp();
306
}
307
308
// Write modified metadata
309
try (FileOutputStream fos = new FileOutputStream(outputFile)) {
310
writer.write(fos, metadata);
311
}
312
313
System.out.println("Metadata processed successfully");
314
315
} catch (IOException | XmlPullParserException e) {
316
System.err.println("Processing failed: " + e.getMessage());
317
}
318
}
319
320
public Metadata mergeMetadataFiles(String[] inputFiles) {
321
MetadataXpp3Reader reader = new MetadataXpp3Reader();
322
Metadata mergedMetadata = null;
323
324
for (String inputFile : inputFiles) {
325
try (FileInputStream fis = new FileInputStream(inputFile)) {
326
Metadata fileMetadata = reader.read(fis);
327
328
if (mergedMetadata == null) {
329
mergedMetadata = fileMetadata;
330
} else {
331
mergedMetadata.merge(fileMetadata);
332
}
333
334
} catch (IOException | XmlPullParserException e) {
335
System.err.println("Error reading " + inputFile + ": " + e.getMessage());
336
}
337
}
338
339
return mergedMetadata;
340
}
341
}
342
```
343
344
## XML Structure
345
346
Repository metadata XML follows this standard structure:
347
348
```xml
349
<?xml version="1.0" encoding="UTF-8"?>
350
<metadata modelVersion="1.1.0">
351
<!-- GroupId-level metadata -->
352
<groupId>org.apache.maven.plugins</groupId>
353
<plugins>
354
<plugin>
355
<name>Apache Maven Compiler Plugin</name>
356
<prefix>compiler</prefix>
357
<artifactId>maven-compiler-plugin</artifactId>
358
</plugin>
359
</plugins>
360
361
<!-- GroupId/ArtifactId-level metadata -->
362
<groupId>com.example</groupId>
363
<artifactId>my-library</artifactId>
364
<versioning>
365
<latest>1.1.0</latest>
366
<release>1.1.0</release>
367
<versions>
368
<version>1.0.0</version>
369
<version>1.1.0</version>
370
</versions>
371
<lastUpdated>20231201143022</lastUpdated>
372
</versioning>
373
374
<!-- GroupId/ArtifactId/Version-level metadata -->
375
<groupId>com.example</groupId>
376
<artifactId>my-library</artifactId>
377
<version>1.2.0-SNAPSHOT</version>
378
<versioning>
379
<snapshot>
380
<timestamp>20231201.143022</timestamp>
381
<buildNumber>1</buildNumber>
382
</snapshot>
383
<lastUpdated>20231201143022</lastUpdated>
384
<snapshotVersions>
385
<snapshotVersion>
386
<extension>jar</extension>
387
<value>1.2.0-20231201.143022-1</value>
388
<updated>20231201143022</updated>
389
</snapshotVersion>
390
<snapshotVersion>
391
<extension>pom</extension>
392
<value>1.2.0-20231201.143022-1</value>
393
<updated>20231201143022</updated>
394
</snapshotVersion>
395
</snapshotVersions>
396
</versioning>
397
</metadata>
398
```
399
400
## Error Handling
401
402
XML processing includes comprehensive error handling:
403
404
- **XmlPullParserException**: Thrown for malformed XML structure
405
- **IOException**: Thrown for file I/O errors during reading/writing
406
- **Strict vs Lenient**: Configurable parsing modes for different error tolerance
407
- **Encoding handling**: Automatic UTF-8 encoding detection and handling
408
- **Resource management**: Proper stream closure with try-with-resources patterns
409
410
## Performance Considerations
411
412
- **Streaming parser**: XPP3 provides memory-efficient pull parsing
413
- **Content transformation**: Applied during parsing for efficiency
414
- **Default entities**: Configurable to optimize parsing speed
415
- **Buffered I/O**: Use BufferedInputStream/BufferedOutputStream for large files