Skip to content

Commit

Permalink
feat: Support xsl:param
Browse files Browse the repository at this point in the history
Fixes: KaotoIO#101

The main part was implemented in KaotoIO#52. This supplements to support primitive source value and primitive target body.
  • Loading branch information
igarashitm committed Apr 1, 2024
1 parent 9b1b2ba commit 7f6e04e
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 6 deletions.
22 changes: 21 additions & 1 deletion packages/ui/src/services/mapping-serializer.service.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { MappingSerializerService, NS_XSL } from './mapping-serializer.service';
import { IDocument, IField, IMapping } from '../models';
import { IDocument, IField, IMapping, PrimitiveDocument } from '../models';
import { DocumentType } from '../models/document';
import * as fs from 'fs';
import { XmlSchemaDocumentService } from './xml-schema-document.service';
Expand All @@ -11,8 +11,10 @@ const sourceParamDoc = XmlSchemaDocumentService.parseXmlSchema(orderXsd);
sourceParamDoc.documentType = DocumentType.PARAM;
sourceParamDoc.name = 'sourceParam1';
sourceParamDoc.documentId = 'sourceParam1';
const sourcePrimitiveParamDoc = new PrimitiveDocument(DocumentType.PARAM, 'primitive');
const targetDoc = XmlSchemaDocumentService.parseXmlSchema(orderXsd);
targetDoc.documentType = DocumentType.TARGET_BODY;
const targetPrimitiveDoc = new PrimitiveDocument(DocumentType.TARGET_BODY, 'primitiveTargetBody');
const domParser = new DOMParser();
const xsltProcessor = new XSLTProcessor();

Expand Down Expand Up @@ -210,5 +212,23 @@ describe('MappingSerializerService', () => {
const notInSchema = item.getElementsByTagName('NotInSchema')[0];
expect(notInSchema).toBeTruthy();
});

it('should serialize primitive parameter to primitive target body mapping', () => {
const serialized = MappingSerializerService.serialize([
{
sourceFields: [sourcePrimitiveParamDoc as IField],
targetFields: [targetPrimitiveDoc as IField],
},
] as IMapping[]);
const xsltDomDocument = domParser.parseFromString(serialized, 'application/xml');
const xslParam = xsltDomDocument
.evaluate('/xsl:stylesheet/xsl:param', xsltDomDocument, null, XPathResult.ANY_TYPE)
.iterateNext() as Element;
expect(xslParam.getAttribute('name')).toEqual('primitive');
const xslValueOf = xsltDomDocument
.evaluate('/xsl:stylesheet/xsl:template/xsl:value-of', xsltDomDocument, null, XPathResult.ANY_TYPE)
.iterateNext() as Element;
expect(xslValueOf.getAttribute('select')).toEqual('$primitive');
});
});
});
17 changes: 12 additions & 5 deletions packages/ui/src/services/mapping-serializer.service.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { DocumentType, IField, IMapping } from '../models';
import { DocumentType, IField, IMapping, PrimitiveDocument } from '../models';
import xmlFormat from 'xml-formatter';

export const NS_XSL = 'http://www.w3.org/1999/XSL/Transform';
Expand Down Expand Up @@ -32,11 +32,14 @@ export class MappingSerializerService {
// Note that `createNSResolver()` returns null with jsdom.
const template = xsltDocument
.evaluate(`/${prefix}:stylesheet/${prefix}:template[@match='/']`, xsltDocument, nsResolver, XPathResult.ANY_TYPE)
.iterateNext();
.iterateNext() as Element;
if (!template || template.nodeType !== Node.ELEMENT_NODE) {
throw Error('No root template in the XSLT document');
}
const parent = MappingSerializerService.getOrCreateParent(template as Element, target);
const parent =
target instanceof PrimitiveDocument
? template
: MappingSerializerService.getOrCreateParent(template as Element, target);
MappingSerializerService.populateSource(parent, source, target);
}

Expand Down Expand Up @@ -72,7 +75,7 @@ export class MappingSerializerService {
static getFieldStack(field: IField, includeItself: boolean = false) {
const fieldStack: IField[] = [];
if (includeItself) fieldStack.push(field);
for (let next = field.parent; 'parent' in next; next = (next as IField).parent) {
for (let next = field.parent; 'parent' in next && next !== next.parent; next = (next as IField).parent) {
fieldStack.push(next);
}
return fieldStack;
Expand All @@ -96,6 +99,10 @@ export class MappingSerializerService {
const valueOf = xsltDocument.createElementNS(NS_XSL, 'value-of');
valueOf.setAttribute('select', sourceXPath);
xslAttribute.appendChild(valueOf);
} else if (target instanceof PrimitiveDocument) {
const valueOf = xsltDocument.createElementNS(NS_XSL, 'value-of');
valueOf.setAttribute('select', sourceXPath);
parent.appendChild(valueOf);
} else if (target.fields.length > 0) {
const copyOf = xsltDocument.createElementNS(NS_XSL, 'copy-of');
copyOf.setAttribute('select', sourceXPath);
Expand Down Expand Up @@ -147,7 +154,7 @@ export class MappingSerializerService {
}
const paramPrefix =
field.ownerDocument.documentType === DocumentType.PARAM ? '$' + field.ownerDocument.documentId : '';
return paramPrefix + '/' + pathStack.join('/');
return field.ownerDocument instanceof PrimitiveDocument ? paramPrefix : paramPrefix + '/' + pathStack.join('/');
}

static getOrCreateNSPrefix(xsltDocument: Document, namespace: string | null) {
Expand Down

0 comments on commit 7f6e04e

Please sign in to comment.