src/XmlHandler.h
author František Kučera <franta-hg@frantovo.cz>
Fri, 31 Jul 2020 00:07:04 +0200
branchv_0
changeset 29 509cac0cf411
parent 23 47a7d86ad810
child 32 1164d5bc5640
permissions -rw-r--r--
xslt: relpipe-out-xhtml: customizable strings and CSS This commands now accepts following parameters: --title --css-appendix --description --record-count-prefix --record-count-suffix --relation-name-prefix --relation-name-suffix and allows to customize (e.g. localize) the XHTML output or override CSS rules by providing own. Attribute names, types and record counts have CSS classes and can be styled or (visually) removed.

/**
 * Relational pipes
 * Copyright © 2018 František Kučera (Frantovo.cz, GlobalCode.info)
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, version 3 of the License.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
#pragma once

#include <string>
#include <vector>
#include <iostream>
#include <sstream>
#include <locale>
#include <codecvt>
#include <regex>

#include <relpipe/reader/typedefs.h>
#include <relpipe/reader/TypeId.h>
#include <relpipe/reader/handlers/RelationalReaderStringHandler.h>
#include <relpipe/reader/handlers/AttributeMetadata.h>
#include <relpipe/xmlwriter/XMLWriter.h>

namespace relpipe {
namespace out {
namespace xml {

using namespace relpipe::reader;
using namespace relpipe::xmlwriter;

class XmlHandler : public handlers::RelationalReaderStringHandler {
private:
	const wstring XMLNS = L"tag:globalcode.info,2018:relpipe";
	shared_ptr<XMLWriter> xmlWriter;
	std::vector<TypeId> columnTypes;
	std::vector<string_t> columnTypeCodes;
	std::vector<string_t> columnNames;
	integer_t valueCount = 0;
	integer_t columnCount = 0;
	integer_t relationCount = 0;

public:

	XmlHandler(std::ostream& output) : xmlWriter(new XMLWriter(output)) {
	}

	void startRelation(string_t name, std::vector<handlers::AttributeMetadata> attributes) override {
		valueCount = 0;
		columnCount = 0;

		if (relationCount == 0) {
			xmlWriter->writeStartElement(L"relpipe",{L"xmlns", XMLNS});
		} else {
			xmlWriter->writeEndElement();
			xmlWriter->writeEndElement();
		}
		relationCount++;
		xmlWriter->writeStartElement(L"relation");

		xmlWriter->writeTextElement(L"name",{}, name);


		xmlWriter->writeStartElement(L"attributes-metadata");
		columnCount = attributes.size();
		columnTypes.resize(columnCount);
		columnTypeCodes.resize(columnCount);
		columnNames.resize(columnCount);
		for (int i = 0; i < attributes.size(); i++) {
			columnNames[i] = attributes[i].getAttributeName();
			columnTypes[i] = attributes[i].getTypeId();
			columnTypeCodes[i] = attributes[i].getTypeName();
			xmlWriter->writeEmptyElement(L"attribute-metadata",{
				L"name", columnNames[i],
				L"type", columnTypeCodes[i]
			});
		}
		xmlWriter->writeEndElement();

		// TODO: print attribute metadata
	}

	void attribute(const string_t& value) override {
		integer_t i = valueCount % columnCount;

		if (i == 0 && valueCount) xmlWriter->writeEndElement();
		if (i == 0) xmlWriter->writeStartElement(L"record");

		valueCount++;

		// TODO: print attribute metadata (only optional, not default)
		xmlWriter->writeTextElement(L"attribute",{
			L"name", columnNames[i],
			L"type", columnTypeCodes[i]
		}, value);

	}

	void endOfPipe() {
		if (valueCount) xmlWriter->writeEndElement();
		if (relationCount) xmlWriter->writeEndElement();
		xmlWriter->writeEndElement();
	}

};

}
}
}