or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

core-model.mdindex.mdplugin-registry.mdsnapshot-management.mdxml-processing.md

xml-processing.mddocs/

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