or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

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

xml-processing.mddocs/

XML Processing

XML reading and writing capabilities for repository metadata files with flexible parsing options, content transformation, and proper encoding handling.

Capabilities

MetadataXpp3Reader

XML parser for reading repository metadata files using XPP3 pull parser with support for strict/lenient parsing and content transformation.

/**
 * XML reader for repository metadata files
 * Uses XPP3 pull parser for efficient streaming XML processing
 */
public class MetadataXpp3Reader {
  // Constructors
  public MetadataXpp3Reader();
  
  /**
   * Constructor with content transformer for value interpolation during parsing
   * @param contentTransformer - Transformer for modifying field values during XML parsing
   */
  public MetadataXpp3Reader(ContentTransformer contentTransformer);
  
  // Reading from InputStream
  /**
   * Read metadata from InputStream with lenient parsing (strict=false)
   * @param input - InputStream containing XML metadata
   * @return Metadata object parsed from XML
   * @throws IOException - If I/O error occurs during reading
   * @throws XmlPullParserException - If XML structure is invalid and cannot be parsed
   */
  public Metadata read(InputStream input) throws IOException, XmlPullParserException;
  
  /**
   * Read metadata from InputStream with configurable parsing strictness
   * @param input - InputStream containing XML metadata
   * @param strict - true for strict validation, false for lenient best-effort parsing
   * @return Metadata object parsed from XML
   * @throws IOException - If I/O error occurs during reading
   * @throws XmlPullParserException - If XML structure is invalid (strict mode) or cannot be parsed at all
   */
  public Metadata read(InputStream input, boolean strict) throws IOException, XmlPullParserException;
  
  // Reading from Reader
  /**
   * Read metadata from Reader with lenient parsing (strict=false)
   * @param reader - Reader containing XML metadata
   * @return Metadata object parsed from XML
   * @throws IOException - If I/O error occurs during reading
   * @throws XmlPullParserException - If XML structure is invalid and cannot be parsed
   */
  public Metadata read(Reader reader) throws IOException, XmlPullParserException;
  
  /**
   * Read metadata from Reader with configurable parsing strictness
   * @param reader - Reader containing XML metadata
   * @param strict - true for strict validation, false for lenient best-effort parsing
   * @return Metadata object parsed from XML
   * @throws IOException - If I/O error occurs during reading
   * @throws XmlPullParserException - If XML structure is invalid (strict mode) or cannot be parsed at all
   */
  public Metadata read(Reader reader, boolean strict) throws IOException, XmlPullParserException;
  
  // Reading from XmlPullParser
  /**
   * Read metadata from pre-configured XmlPullParser
   * @param parser - XmlPullParser positioned at metadata element
   * @param strict - true for strict validation, false for lenient best-effort parsing
   * @return Metadata object parsed from XML
   * @throws IOException - If I/O error occurs during reading
   * @throws XmlPullParserException - If XML structure is invalid (strict mode) or cannot be parsed at all
   */
  public Metadata read(XmlPullParser parser, boolean strict) throws IOException, XmlPullParserException;
  
  // Configuration
  /**
   * Check if default XML entities are loaded during parsing
   * @return true if default entities are loaded, false otherwise
   */
  public boolean getAddDefaultEntities();
  
  /**
   * Configure whether to load default XML entities during parsing
   * @param addDefaultEntities - true to load XHTML entities (lat1, special, symbol), false otherwise
   */
  public void setAddDefaultEntities(boolean addDefaultEntities);
}

Usage Examples:

import org.apache.maven.artifact.repository.metadata.Metadata;
import org.apache.maven.artifact.repository.metadata.io.xpp3.MetadataXpp3Reader;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;
import org.xmlpull.v1.XmlPullParserException;

// Basic reading from file
MetadataXpp3Reader reader = new MetadataXpp3Reader();
try (FileInputStream fis = new FileInputStream("repository-metadata.xml")) {
    Metadata metadata = reader.read(fis);
    System.out.println("GroupId: " + metadata.getGroupId());
    System.out.println("ArtifactId: " + metadata.getArtifactId());
} catch (IOException | XmlPullParserException e) {
    System.err.println("Error reading metadata: " + e.getMessage());
}

// Reading with strict mode (validation enabled)
try (FileReader fileReader = new FileReader("repository-metadata.xml")) {
    Metadata metadata = reader.read(fileReader, true); // strict=true
    // Strict mode will throw exceptions for invalid XML structure
} catch (IOException | XmlPullParserException e) {
    System.err.println("Invalid metadata file: " + e.getMessage());
}

// Reading with lenient mode (best-effort parsing)
try (FileInputStream fis = new FileInputStream("repository-metadata.xml")) {
    Metadata metadata = reader.read(fis, false); // strict=false
    // Lenient mode attempts to parse even malformed XML
} catch (IOException | XmlPullParserException e) {
    System.err.println("Could not parse metadata: " + e.getMessage());
}

// Configure default entities
reader.setAddDefaultEntities(true);
boolean hasDefaultEntities = reader.getAddDefaultEntities();

MetadataXpp3Writer

XML writer for writing repository metadata files with proper formatting and encoding support.

/**
 * XML writer for repository metadata files
 * Generates properly formatted XML with UTF-8 encoding
 */
public class MetadataXpp3Writer {
  // Constructor
  public MetadataXpp3Writer();
  
  // Writing to Writer
  /**
   * Write metadata to Writer as formatted XML
   * @param writer - Writer to write XML content to
   * @param metadata - Metadata object to serialize to XML
   * @throws IOException - If I/O error occurs during writing
   */
  public void write(Writer writer, Metadata metadata) throws IOException;
  
  // Writing to OutputStream
  /**
   * Write metadata to OutputStream as formatted XML with UTF-8 encoding
   * @param output - OutputStream to write XML content to
   * @param metadata - Metadata object to serialize to XML
   * @throws IOException - If I/O error occurs during writing
   */
  public void write(OutputStream output, Metadata metadata) throws IOException;
  
  // Configuration
  /**
   * Set optional file comment to include in generated XML
   * @param fileComment - Comment text to include at top of XML file, or null for no comment
   */
  public void setFileComment(String fileComment);
}

Usage Examples:

import org.apache.maven.artifact.repository.metadata.Metadata;
import org.apache.maven.artifact.repository.metadata.Versioning;
import org.apache.maven.artifact.repository.metadata.io.xpp3.MetadataXpp3Writer;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;

// Create metadata to write
Metadata metadata = new Metadata();
metadata.setGroupId("com.example");
metadata.setArtifactId("my-library");

Versioning versioning = new Versioning();
versioning.addVersion("1.0.0");
versioning.addVersion("1.1.0");
versioning.setLatest("1.1.0");
versioning.setRelease("1.1.0");
versioning.updateTimestamp();
metadata.setVersioning(versioning);

// Write to file using Writer
MetadataXpp3Writer writer = new MetadataXpp3Writer();
try (FileWriter fileWriter = new FileWriter("output-metadata.xml")) {
    writer.write(fileWriter, metadata);
    System.out.println("Metadata written successfully");
} catch (IOException e) {
    System.err.println("Error writing metadata: " + e.getMessage());
}

// Write to file using OutputStream
try (FileOutputStream fos = new FileOutputStream("output-metadata.xml")) {
    writer.write(fos, metadata);
} catch (IOException e) {
    System.err.println("Error writing metadata: " + e.getMessage());
}

// Set file comment
writer.setFileComment("Generated by Maven Repository Metadata");
try (FileWriter fileWriter = new FileWriter("commented-metadata.xml")) {
    writer.write(fileWriter, metadata);
}

ContentTransformer Interface

Content transformation interface for modifying XML content during parsing, useful for preprocessing or filtering XML data.

/**
 * Static nested interface in MetadataXpp3Reader for transforming content during XML parsing
 * Allows modification of field values as they are read from XML
 */
public static interface ContentTransformer {
  /**
   * Interpolate the value read from the xpp3 document
   * @param source The source value
   * @param fieldName A description of the field being interpolated
   * @return The interpolated value
   */
  String transform(String source, String fieldName);
}

Usage Examples:

import org.apache.maven.artifact.repository.metadata.io.xpp3.MetadataXpp3Reader;
import org.apache.maven.artifact.repository.metadata.io.xpp3.MetadataXpp3Reader.ContentTransformer;
import java.io.FileInputStream;

// Create content transformer to modify version strings
ContentTransformer transformer = new ContentTransformer() {
    @Override
    public String transform(String source, String fieldName) {
        if ("version".equals(fieldName)) {
            // Transform version format during parsing
            return source.replace("-SNAPSHOT", "-SNAPSHOT-CUSTOM");
        }
        return source; // No transformation for other fields
    }
};

// Use transformer during reading
MetadataXpp3Reader reader = new MetadataXpp3Reader(transformer);
try (FileInputStream fis = new FileInputStream("repository-metadata.xml")) {
    Metadata metadata = reader.read(fis);
    // All version strings will have been transformed during parsing
} catch (Exception e) {
    System.err.println("Error: " + e.getMessage());
}

// Lambda-based transformer for timestamp formatting
ContentTransformer timestampTransformer = (source, fieldName) -> {
    if ("lastUpdated".equals(fieldName) && source != null) {
        // Ensure timestamp is in correct format
        return source.replaceAll("[^0-9]", "");
    }
    return source;
};

MetadataXpp3Reader readerWithTimestampTransform = new MetadataXpp3Reader(timestampTransformer);

XML Processing Workflow

Complete workflow for reading, modifying, and writing repository metadata files.

Typical Processing Pattern:

import org.apache.maven.artifact.repository.metadata.Metadata;
import org.apache.maven.artifact.repository.metadata.io.xpp3.MetadataXpp3Reader;
import org.apache.maven.artifact.repository.metadata.io.xpp3.MetadataXpp3Writer;
import java.io.*;

public class MetadataProcessor {
    
    public void processMetadata(String inputFile, String outputFile) {
        MetadataXpp3Reader reader = new MetadataXpp3Reader();
        MetadataXpp3Writer writer = new MetadataXpp3Writer();
        
        try {
            // Read existing metadata
            Metadata metadata;
            try (FileInputStream fis = new FileInputStream(inputFile)) {
                metadata = reader.read(fis, false); // lenient parsing
            }
            
            // Process/modify metadata
            if (metadata.getVersioning() != null) {
                metadata.getVersioning().updateTimestamp();
            }
            
            // Write modified metadata
            try (FileOutputStream fos = new FileOutputStream(outputFile)) {
                writer.write(fos, metadata);
            }
            
            System.out.println("Metadata processed successfully");
            
        } catch (IOException | XmlPullParserException e) {
            System.err.println("Processing failed: " + e.getMessage());
        }
    }
    
    public Metadata mergeMetadataFiles(String[] inputFiles) {
        MetadataXpp3Reader reader = new MetadataXpp3Reader();
        Metadata mergedMetadata = null;
        
        for (String inputFile : inputFiles) {
            try (FileInputStream fis = new FileInputStream(inputFile)) {
                Metadata fileMetadata = reader.read(fis);
                
                if (mergedMetadata == null) {
                    mergedMetadata = fileMetadata;
                } else {
                    mergedMetadata.merge(fileMetadata);
                }
                
            } catch (IOException | XmlPullParserException e) {
                System.err.println("Error reading " + inputFile + ": " + e.getMessage());
            }
        }
        
        return mergedMetadata;
    }
}

XML Structure

Repository metadata XML follows this standard structure:

<?xml version="1.0" encoding="UTF-8"?>
<metadata modelVersion="1.1.0">
  <!-- GroupId-level metadata -->
  <groupId>org.apache.maven.plugins</groupId>
  <plugins>
    <plugin>
      <name>Apache Maven Compiler Plugin</name>
      <prefix>compiler</prefix>
      <artifactId>maven-compiler-plugin</artifactId>
    </plugin>
  </plugins>
  
  <!-- GroupId/ArtifactId-level metadata -->
  <groupId>com.example</groupId>
  <artifactId>my-library</artifactId>
  <versioning>
    <latest>1.1.0</latest>
    <release>1.1.0</release>
    <versions>
      <version>1.0.0</version>
      <version>1.1.0</version>
    </versions>
    <lastUpdated>20231201143022</lastUpdated>
  </versioning>
  
  <!-- GroupId/ArtifactId/Version-level metadata -->
  <groupId>com.example</groupId>
  <artifactId>my-library</artifactId>
  <version>1.2.0-SNAPSHOT</version>
  <versioning>
    <snapshot>
      <timestamp>20231201.143022</timestamp>
      <buildNumber>1</buildNumber>
    </snapshot>
    <lastUpdated>20231201143022</lastUpdated>
    <snapshotVersions>
      <snapshotVersion>
        <extension>jar</extension>
        <value>1.2.0-20231201.143022-1</value>
        <updated>20231201143022</updated>
      </snapshotVersion>
      <snapshotVersion>
        <extension>pom</extension>
        <value>1.2.0-20231201.143022-1</value>
        <updated>20231201143022</updated>
      </snapshotVersion>
    </snapshotVersions>
  </versioning>
</metadata>

Error Handling

XML processing includes comprehensive error handling:

  • XmlPullParserException: Thrown for malformed XML structure
  • IOException: Thrown for file I/O errors during reading/writing
  • Strict vs Lenient: Configurable parsing modes for different error tolerance
  • Encoding handling: Automatic UTF-8 encoding detection and handling
  • Resource management: Proper stream closure with try-with-resources patterns

Performance Considerations

  • Streaming parser: XPP3 provides memory-efficient pull parsing
  • Content transformation: Applied during parsing for efficiency
  • Default entities: Configurable to optimize parsing speed
  • Buffered I/O: Use BufferedInputStream/BufferedOutputStream for large files