Created
December 14, 2021 07:13
-
-
Save chumpa/68cd3c15114354b9ec1a4e288b84c35d to your computer and use it in GitHub Desktop.
XmlMapper.groovy
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import groovy.util.slurpersupport.GPathResult | |
import groovy.xml.StreamingMarkupBuilder | |
import groovy.xml.streamingmarkupsupport.BaseMarkupBuilder | |
import javax.xml.transform.OutputKeys | |
import javax.xml.transform.Source | |
import javax.xml.transform.Transformer | |
import javax.xml.transform.TransformerFactory | |
import javax.xml.transform.stream.StreamResult | |
import javax.xml.transform.stream.StreamSource | |
import java.time.Clock | |
import java.time.Instant | |
import java.time.ZoneId | |
import java.time.format.DateTimeFormatter | |
class XmlMapper { | |
private ZoneId zoneId = null | |
private Clock clock = null | |
Instant t0, t1, t2, t3 | |
private XmlSlurper xp = new XmlSlurper(false, true) | |
private GPathResult root = null | |
StreamingMarkupBuilder sb = new StreamingMarkupBuilder() | |
BaseMarkupBuilder.Document xmlbinding = null | |
ByteArrayOutputStream baos = null | |
XmlMapper(ZoneId zoneId = ZoneId.of("Europe/Moscow")) { | |
this.zoneId = zoneId | |
this.clock = Clock.system(zoneId) | |
} | |
GPathResult getRoot() { | |
root | |
} | |
Instant now() { | |
Instant.now(clock) | |
} | |
// 132 это длина текстов в айдоке | |
static List<String> splitText(String contentText, int limit = 132) { | |
return contentText.findAll(".{$limit}|.+") | |
} | |
// когда слева 0..1 и копируем направо, глядя не на содержимое а на наличие элемента/атрибута | |
void copy0__1(String name, GPathResult content, Closure<String> z = { String x -> x }) { | |
assert xmlbinding != null | |
int sz = content.size() | |
if (sz > 0) xmlbinding."$name"(z.call(content.text())) | |
} | |
String statistic() { | |
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssz").withZone(zoneId) | |
String pt = t1.minusMillis(t0.toEpochMilli()).toEpochMilli() | |
String ft = t3.minusMillis(t2.toEpochMilli()).toEpochMilli() | |
String x = dtf.format(this.t3) | |
"разбор: $pt ms, формирование xml: $ft ms, завершено в $x" | |
} | |
private GPathResult parse(def payload) { | |
t0 = now() | |
if (payload instanceof String) | |
root = xp.parseText(payload) | |
else | |
root = xp.parse(payload) | |
t1 = now() | |
return root | |
} | |
/** | |
* Оптимизировано для русских букв в строках и комментах | |
* @param source | |
* @param target | |
*/ | |
long serialize(Writable source, Writer target, boolean indent = false, int indentNum = 0) { | |
Instant t4 = now() | |
baos = new ByteArrayOutputStream(512) | |
source.writeTo(baos.newWriter("UTF-8")) // UTF-8 здесь важно для комментариев на русском языке | |
baos.close() | |
TransformerFactory factory = TransformerFactory.newInstance() | |
if (indent) { | |
factory.setAttribute("indent-number", indentNum) | |
} | |
Transformer transformer = factory.newTransformer() | |
transformer.setOutputProperty(OutputKeys.INDENT, indent ? "yes" : "no") | |
transformer.setOutputProperty(OutputKeys.METHOD, "xml") | |
transformer.setOutputProperty(OutputKeys.MEDIA_TYPE, "text/xml") | |
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8") | |
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no") | |
transformer.setOutputProperty(OutputKeys.STANDALONE, "yes") | |
transformer.setOutputProperty(OutputKeys.VERSION, "1.0") | |
Source xml = new StreamSource(new ByteArrayInputStream(baos.toByteArray())) | |
transformer.transform(xml, new StreamResult(target)) | |
return now().minusMillis(t4.toEpochMilli()).toEpochMilli() | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment