or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

builders.mdentities.mdindex.mdjaxb.mdnamespaces.mdnavigation.mdparsing.mdstreaming.mdutilities.md

namespaces.mddocs/

0

# Namespace Support

1

2

Groovy XML provides comprehensive namespace support for creating, parsing, and navigating XML documents with proper namespace handling, including namespace-aware builders, parsers, and navigation tools.

3

4

## Namespace Class

5

6

Core class for managing XML namespaces and creating qualified names.

7

8

```java { .api }

9

public class Namespace {

10

// Constructors

11

public Namespace();

12

public Namespace(String uri);

13

public Namespace(String uri, String prefix);

14

15

// Core methods

16

public QName get(String localName);

17

public String getPrefix();

18

public String getUri();

19

20

// Utility methods

21

@Override

22

public boolean equals(Object obj);

23

@Override

24

public int hashCode();

25

@Override

26

public String toString();

27

}

28

```

29

30

### Namespace Usage

31

32

```groovy

33

// Create namespaces

34

def defaultNs = new Namespace('http://example.com/default')

35

def metaNs = new Namespace('http://example.com/metadata', 'meta')

36

def dataNs = new Namespace('http://example.com/data', 'data')

37

38

// Create qualified names

39

def titleQName = metaNs.get('title')

40

def itemQName = dataNs.get('item')

41

def rootQName = defaultNs.get('root')

42

43

println titleQName // {http://example.com/metadata}title

44

println itemQName // {http://example.com/data}item

45

46

// Use in builders

47

def xml = new MarkupBuilder(writer)

48

xml."${rootQName}" {

49

"${titleQName}"('Document Title')

50

"${itemQName}"(id: '1', 'Item content')

51

}

52

```

53

54

## QName Support

55

56

QName class for representing qualified XML names with namespace information.

57

58

```java { .api }

59

public class QName {

60

// Constructors

61

public QName(String localName);

62

public QName(String namespaceURI, String localName);

63

public QName(String namespaceURI, String localName, String prefix);

64

65

// Accessor methods

66

public String getLocalName();

67

public String getNamespaceURI();

68

public String getPrefix();

69

70

// Utility methods

71

@Override

72

public boolean equals(Object obj);

73

@Override

74

public int hashCode();

75

@Override

76

public String toString();

77

}

78

```

79

80

### QName Usage

81

82

```groovy

83

// Create QNames directly

84

def qname1 = new QName('title')

85

def qname2 = new QName('http://example.com/ns', 'title')

86

def qname3 = new QName('http://example.com/ns', 'title', 'ns')

87

88

// Access QName properties

89

println qname3.localName // "title"

90

println qname3.namespaceURI // "http://example.com/ns"

91

println qname3.prefix // "ns"

92

93

// Use in XML operations

94

def builder = new MarkupBuilder(writer)

95

builder."${qname3}" {

96

content('Namespaced content')

97

}

98

```

99

100

## Namespace-Aware Building

101

102

### MarkupBuilder with Namespaces

103

104

```groovy

105

def xml = new MarkupBuilder(writer)

106

107

// Method 1: Explicit namespace declarations

108

xml.root(

109

'xmlns': 'http://example.com/default',

110

'xmlns:meta': 'http://example.com/metadata',

111

'xmlns:data': 'http://example.com/data'

112

) {

113

'meta:header' {

114

'meta:title'('Document Title')

115

'meta:created'(new Date().toString())

116

}

117

118

'data:content' {

119

'data:item'(id: '1') {

120

'data:name'('Item 1')

121

'data:value'('Value 1')

122

}

123

'data:item'(id: '2') {

124

'data:name'('Item 2')

125

'data:value'('Value 2')

126

}

127

}

128

}

129

130

// Method 2: Using Namespace objects

131

def defaultNs = new Namespace('http://example.com/default')

132

def metaNs = new Namespace('http://example.com/metadata', 'meta')

133

def dataNs = new Namespace('http://example.com/data', 'data')

134

135

xml."${defaultNs.get('document')}"(

136

'xmlns': defaultNs.uri,

137

'xmlns:meta': metaNs.uri,

138

'xmlns:data': dataNs.uri

139

) {

140

"${metaNs.get('metadata')}" {

141

"${metaNs.get('title')}"('Namespace Document')

142

}

143

144

"${dataNs.get('records')}" {

145

(1..3).each { i ->

146

"${dataNs.get('record')}"(id: i) {

147

"${dataNs.get('value')}"("Record ${i}")

148

}

149

}

150

}

151

}

152

```

153

154

### StreamingMarkupBuilder with Namespaces

155

156

```groovy

157

def smb = new StreamingMarkupBuilder()

158

def content = smb.bind {

159

mkp.xmlDeclaration(version: '1.0', encoding: 'UTF-8')

160

161

// Define namespace mappings

162

namespaces = [

163

'': 'http://example.com/default',

164

'meta': 'http://example.com/metadata',

165

'data': 'http://example.com/data',

166

'custom': 'http://example.com/custom'

167

]

168

169

document(

170

xmlns: namespaces[''],

171

'xmlns:meta': namespaces['meta'],

172

'xmlns:data': namespaces['data'],

173

'xmlns:custom': namespaces['custom']

174

) {

175

176

'meta:header' {

177

'meta:title'('Streaming Namespace Document')

178

'meta:generator'('Groovy StreamingMarkupBuilder')

179

}

180

181

'data:body' {

182

(1..100).each { i ->

183

'data:record'(id: i, 'custom:priority': i % 3) {

184

'data:content'("Content ${i}")

185

'custom:metadata' {

186

'custom:category'("Category ${i % 5}")

187

'custom:tags' {

188

(1..(i % 3 + 1)).each { j ->

189

'custom:tag'("tag${j}")

190

}

191

}

192

}

193

}

194

}

195

}

196

}

197

}

198

199

content.writeTo(new FileWriter('namespaced-streaming.xml'))

200

```

201

202

## Namespace-Aware Parsing

203

204

### XmlParser with Namespaces

205

206

```groovy

207

// Create namespace-aware parser

208

def parser = new XmlParser(false, true) // not validating, namespace aware

209

def nsXml = '''<?xml version="1.0" encoding="UTF-8"?>

210

<root xmlns="http://example.com/default"

211

xmlns:meta="http://example.com/metadata"

212

xmlns:data="http://example.com/data">

213

<meta:header>

214

<meta:title>Sample Document</meta:title>

215

<meta:version>1.0</meta:version>

216

</meta:header>

217

<data:content>

218

<data:item id="1">

219

<data:name>Item 1</data:name>

220

<data:value>Value 1</data:value>

221

</data:item>

222

<data:item id="2">

223

<data:name>Item 2</data:name>

224

<data:value>Value 2</data:value>

225

</data:item>

226

</data:content>

227

</root>'''

228

229

def root = parser.parseText(nsXml)

230

231

// Access namespaced elements

232

println root.name() // Will include namespace information

233

def header = root['meta:header'][0]

234

def title = header['meta:title'][0].text()

235

def items = root['data:content'][0]['data:item']

236

237

items.each { item ->

238

def name = item['data:name'][0].text()

239

def value = item['data:value'][0].text()

240

println "Item: ${name} = ${value}"

241

}

242

243

// Check namespace information

244

def itemNode = items[0]

245

println "Namespace URI: ${itemNode.namespaceURI}"

246

println "Local name: ${itemNode.localName}"

247

```

248

249

### XmlSlurper with Namespaces

250

251

```groovy

252

// Create namespace-aware slurper

253

def slurper = new XmlSlurper(false, true) // not validating, namespace aware

254

def nsDoc = slurper.parseText(nsXml)

255

256

// Navigate with namespace prefixes

257

println nsDoc.'meta:header'.'meta:title'.text()

258

println nsDoc.'data:content'.'data:item'.size()

259

260

// Access all items

261

nsDoc.'data:content'.'data:item'.each { item ->

262

println "ID: ${item.'@id'}"

263

println "Name: ${item.'data:name'.text()}"

264

println "Value: ${item.'data:value'.text()}"

265

}

266

267

// Declare namespace mappings for easier access

268

def mappedDoc = nsDoc.declareNamespace([

269

'default': 'http://example.com/default',

270

'm': 'http://example.com/metadata',

271

'd': 'http://example.com/data'

272

])

273

274

// Use shorter prefixes

275

println mappedDoc.'m:header'.'m:title'.text()

276

println mappedDoc.'d:content'.'d:item'.'d:name'.text()

277

278

// Look up namespace URIs

279

println nsDoc.lookupNamespace('meta') // "http://example.com/metadata"

280

println nsDoc.lookupNamespace('data') // "http://example.com/data"

281

```

282

283

## NamespaceBuilder Support

284

285

### NamespaceBuilder

286

287

Builder with enhanced namespace support for complex namespace scenarios.

288

289

```java { .api }

290

public class NamespaceBuilder extends NamespaceBuilderSupport {

291

// Constructors

292

public NamespaceBuilder();

293

public NamespaceBuilder(Writer writer);

294

295

// Namespace-aware building methods inherited from parent

296

}

297

```

298

299

### NamespaceBuilderSupport

300

301

Base class providing namespace-aware building functionality.

302

303

```java { .api }

304

public abstract class NamespaceBuilderSupport extends BuilderSupport {

305

// Namespace management

306

protected Map<String, String> namespaceMethodMap;

307

protected boolean autoPrefix;

308

309

// Configuration methods

310

public void setAutoPrefix(boolean autoPrefix);

311

public boolean getAutoPrefix();

312

313

// Namespace declaration methods

314

public void declareNamespace(String prefix, String namespaceURI);

315

public void declareNamespace(Map<String, String> namespaceMap);

316

}

317

```

318

319

### NamespaceBuilder Usage

320

321

```groovy

322

def nsBuilder = new NamespaceBuilder(writer)

323

324

// Configure automatic prefixing

325

nsBuilder.setAutoPrefix(true)

326

327

// Declare namespaces

328

nsBuilder.declareNamespace('meta', 'http://example.com/metadata')

329

nsBuilder.declareNamespace('data', 'http://example.com/data')

330

331

// Build with automatic namespace handling

332

nsBuilder.root {

333

'meta:information' {

334

'meta:title'('Auto-prefixed Document')

335

'meta:description'('Demonstrates automatic namespace handling')

336

}

337

338

'data:records' {

339

record(id: '1') {

340

'data:content'('Content 1')

341

}

342

record(id: '2') {

343

'data:content'('Content 2')

344

}

345

}

346

}

347

```

348

349

## Advanced Namespace Patterns

350

351

### Dynamic Namespace Assignment

352

353

```groovy

354

def createNamespacedDocument = { namespaceMap, data ->

355

def smb = new StreamingMarkupBuilder()

356

357

smb.bind {

358

mkp.xmlDeclaration(version: '1.0', encoding: 'UTF-8')

359

360

// Create root with all namespace declarations

361

def rootAttrs = [:]

362

namespaceMap.each { prefix, uri ->

363

def attrName = prefix ? "xmlns:${prefix}" : 'xmlns'

364

rootAttrs[attrName] = uri

365

}

366

367

document(rootAttrs) {

368

// Use namespaces dynamically

369

data.each { section ->

370

def prefix = section.namespace ?: ''

371

def elementName = prefix ? "${prefix}:${section.name}" : section.name

372

373

"${elementName}"(section.attributes ?: [:]) {

374

section.children?.each { child ->

375

def childPrefix = child.namespace ?: ''

376

def childName = childPrefix ? "${childPrefix}:${child.name}" : child.name

377

"${childName}"(child.content)

378

}

379

}

380

}

381

}

382

}

383

}

384

385

// Usage

386

def namespaces = [

387

'': 'http://example.com/default',

388

'meta': 'http://example.com/metadata',

389

'data': 'http://example.com/data'

390

]

391

392

def documentData = [

393

[name: 'header', namespace: 'meta', children: [

394

[name: 'title', content: 'Dynamic Document'],

395

[name: 'version', content: '1.0']

396

]],

397

[name: 'content', namespace: 'data', children: [

398

[name: 'item', content: 'Item 1'],

399

[name: 'item', content: 'Item 2']

400

]]

401

]

402

403

def result = createNamespacedDocument(namespaces, documentData)

404

result.writeTo(new FileWriter('dynamic-namespaces.xml'))

405

```

406

407

### Namespace Validation and Resolution

408

409

```groovy

410

class NamespaceValidator {

411

412

static boolean validateNamespaces(GPathResult doc) {

413

def namespaces = [:]

414

415

// Collect all namespace declarations

416

doc.depthFirst().each { node ->

417

node.attributes().each { name, value ->

418

if (name.startsWith('xmlns')) {

419

def prefix = name == 'xmlns' ? '' : name.substring(6)

420

namespaces[prefix] = value

421

}

422

}

423

}

424

425

// Validate all prefixed elements have declarations

426

def valid = true

427

doc.depthFirst().each { node ->

428

def nodeName = node.name()

429

if (nodeName.contains(':')) {

430

def prefix = nodeName.split(':')[0]

431

if (!namespaces.containsKey(prefix)) {

432

println "Undeclared namespace prefix: ${prefix}"

433

valid = false

434

}

435

}

436

}

437

438

return valid

439

}

440

441

static Map<String, String> extractNamespaces(GPathResult doc) {

442

def namespaces = [:]

443

444

doc.depthFirst().each { node ->

445

node.attributes().each { name, value ->

446

if (name.startsWith('xmlns')) {

447

def prefix = name == 'xmlns' ? '' : name.substring(6)

448

namespaces[prefix] = value

449

}

450

}

451

}

452

453

return namespaces

454

}

455

}

456

457

// Usage

458

def slurper = new XmlSlurper(false, true)

459

def doc = slurper.parseText(namespacedXml)

460

461

def isValid = NamespaceValidator.validateNamespaces(doc)

462

def namespaces = NamespaceValidator.extractNamespaces(doc)

463

464

println "Document valid: ${isValid}"

465

println "Namespaces: ${namespaces}"

466

```

467

468

### Namespace-Aware Transformation

469

470

```groovy

471

def transformWithNamespaces = { inputXml, transformationRules ->

472

def slurper = new XmlSlurper(false, true)

473

def doc = slurper.parseText(inputXml)

474

475

def smb = new StreamingMarkupBuilder()

476

def result = smb.bind {

477

mkp.xmlDeclaration(version: '1.0', encoding: 'UTF-8')

478

479

// Extract and preserve namespaces

480

def nsDeclarations = [:]

481

doc.attributes().each { name, value ->

482

if (name.toString().startsWith('xmlns')) {

483

nsDeclarations[name] = value

484

}

485

}

486

487

transformedDocument(nsDeclarations) {

488

// Apply transformation rules while preserving namespaces

489

doc.children().each { child ->

490

def childName = child.name()

491

def rule = transformationRules[childName]

492

493

if (rule) {

494

"${rule.newName ?: childName}"(rule.newAttributes ?: [:]) {

495

if (rule.transform) {

496

rule.transform(child)

497

} else {

498

// Copy child content preserving namespaces

499

child.children().each { grandchild ->

500

"${grandchild.name()}"(grandchild.text())

501

}

502

}

503

}

504

}

505

}

506

}

507

}

508

509

return result

510

}

511

512

// Usage

513

def rules = [

514

'meta:header': [

515

newName: 'header',

516

transform: { node ->

517

'title'(node.'meta:title'.text().toUpperCase())

518

'processed'(new Date().toString())

519

}

520

],

521

'data:content': [

522

newName: 'processedData',

523

transform: { node ->

524

node.'data:item'.each { item ->

525

processedItem(id: item.'@id') {

526

originalName(item.'data:name'.text())

527

processedValue(item.'data:value'.text().reverse())

528

}

529

}

530

}

531

]

532

]

533

534

def transformed = transformWithNamespaces(namespacedXml, rules)

535

transformed.writeTo(new FileWriter('transformed.xml'))

536

```

537

538

## Namespace Best Practices

539

540

```groovy

541

class NamespaceBestPractices {

542

543

// Always use meaningful namespace URIs

544

static final Map<String, String> STANDARD_NAMESPACES = [

545

'xsi': 'http://www.w3.org/2001/XMLSchema-instance',

546

'xs': 'http://www.w3.org/2001/XMLSchema',

547

'xml': 'http://www.w3.org/XML/1998/namespace'

548

]

549

550

static void declareStandardNamespaces(MarkupBuilder builder) {

551

// Always declare standard namespaces when needed

552

STANDARD_NAMESPACES.each { prefix, uri ->

553

builder."xmlns:${prefix}" = uri

554

}

555

}

556

557

static String createNamespaceURI(String organization, String component, String version = null) {

558

def uri = "http://${organization}/schemas/${component}"

559

return version ? "${uri}/${version}" : uri

560

}

561

562

static boolean isValidNamespaceURI(String uri) {

563

// Basic validation for namespace URIs

564

return uri ==~ /^https?:\/\/.+/ || uri ==~ /^urn:.+/

565

}

566

567

static void validateAndBuild(Map<String, String> namespaces, Closure xmlContent) {

568

// Validate all namespace URIs before building

569

namespaces.each { prefix, uri ->

570

if (!isValidNamespaceURI(uri)) {

571

throw new IllegalArgumentException("Invalid namespace URI: ${uri}")

572

}

573

}

574

575

def smb = new StreamingMarkupBuilder()

576

def result = smb.bind {

577

mkp.xmlDeclaration(version: '1.0', encoding: 'UTF-8')

578

579

def rootAttrs = [:]

580

namespaces.each { prefix, uri ->

581

def attrName = prefix ? "xmlns:${prefix}" : 'xmlns'

582

rootAttrs[attrName] = uri

583

}

584

585

document(rootAttrs, xmlContent)

586

}

587

588

return result

589

}

590

}

591

```