【译】使用Moustache模板转换XML

194 阅读2分钟

从HTTP-RPC 7.4开始,TemplateEncoder类可用于使用类似于Mustache的轻量级语法来转换XML。

尽管XSLT是将XML文档转换为备用表示形式的强大而灵活的方法,但在实践中通常很难且不便使用。XSLT规范又大又复杂,并且平台支持不一致。

从HTTP-RPC 7.4开始,TemplateEncoder该类可用于使用类似于Mustache的轻量级语法来转换XML 。新ElementAdapter类Element通过Map接口提供对XML DOM内容的访问。该地图的内容可以通过模板文档轻松转换为其他表示形式。

例如,来自W3 Schools的本教程使用XML来建模一个简单的早餐菜单:

<breakfast_menu> Belgian Waffles $5.95 Two of our famous Belgian Waffles with plenty of real maple syrup 650

<food>
    <name>Strawberry Belgian Waffles</name>
    <price>$7.95</price>
    <description>Light Belgian waffles covered with strawberries and whipped cream</description>
    <calories>900</calories>
</food>

<food>
    <name>Berry-Berry Belgian Waffles</name>
    <price>$8.95</price>
    <description>Light Belgian waffles covered with an assortment of fresh berries and whipped cream</description>
    <calories>900</calories>
</food>

<food>
    <name>French Toast</name>
    <price>$4.50</price>
    <description>Thick slices made from our homemade sourdough bread</description>
    <calories>600</calories>
</food>

<food>
    <name>Homestyle Breakfast</name>
    <price>$6.95</price>
    <description>Two eggs, bacon or sausage, toast, and our ever-popular hash browns</description>
    <calories>950</calories>
</food>

</breakfast_menu>

该示例使用以下XSLT模板将标记转换为HTML。即使在这个相当简单的示例中,XSLT的冗长也是显而易见的,并且对可读性具有负面影响:

<?xml version="1.0" encoding="UTF-8"?>
<html xsl:version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <body style="font-family:Arial;font-size:12pt;background-color:#EEEEEE">
        <xsl:for-each select="breakfast_menu/food">
            <div style="background-color:teal;color:white;padding:4px">
                <span style="font-weight:bold"><xsl:value-of select="name"/> - </span>
                <xsl:value-of select="price"/>
            </div>
            <div style="margin-left:20px;margin-bottom:1em;font-size:10pt">
                <p>
                    <xsl:value-of select="description"/>
                    <span style="font-style:italic"> (<xsl:value-of select="calories"/> calories per serving)</span>
                </p>
            </div>
        </xsl:for-each>
    </body>
</html>

本javax.xml.transform.Transformer类可用于应用的模板XML文档:

Source source = new StreamSource(getClass().getResourceAsStream("breakfast_menu.xslt"));

Transformer transformer = TransformerFactory.newInstance().newTransformer(source);

Source xmlSource = new StreamSource(getClass().getResourceAsStream("breakfast_menu.xml"));

File homeDirectory = new File(System.getProperty("user.home"));
File outputFile = new File(homeDirectory, "breakfast_menu_1.html");

try (FileOutputStream outputStream = new FileOutputStream(outputFile)) {
    transformer.transform(xmlSource, new StreamResult(outputStream));
}

转换的结果如下所示:

以下是如何使用Mustache样式语法定义相似模板的示例。它比以前的版本更简单易读,并且可以使用任何支持HTML的文本编辑器进行编辑:

<!-- Breakfast Menu -->
<html>
    <body style="font-family:Arial;font-size:12pt;background-color:#EEEEEE">
        <!-- {{#food*}} -->
            <div style="background-color:teal;color:white;padding:4px">
                <span style="font-weight:bold">{{name}} - </span>
                {{price}}
            </div>
            <div style="margin-left:20px;margin-bottom:1em;font-size:10pt">
                <p>
                    {{description}}
                    <span style="font-style:italic"> ({{calories}} calories per serving)</span>
                </p>
            </div>
        <!-- {{/food*}} -->
    </body>
</html>

此代码使用以下命令将模板应用于XML文档TemplateEncoder:

DocumentBuilder documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();

Document document;
try (InputStream inputStream = getClass().getResourceAsStream("breakfast_menu.xml")) {
    document = documentBuilder.parse(inputStream);
}

TemplateEncoder templateEncoder = new TemplateEncoder(getClass().getResource("breakfast_menu.html"));

File homeDirectory = new File(System.getProperty("user.home"));
File outputFile = new File(homeDirectory, "breakfast_menu_2.html");

try (FileOutputStream outputStream = new FileOutputStream(outputFile)) {
    templateEncoder.write(new ElementAdapter(document.getDocumentElement()), outputStream);
}

结果与XSLT版本相同:

简单并不是胡子风格方法的唯一优势。平均而言,XSLTTransformer版本运行大约需要350毫秒,而运行XSLT的版本大约需要30毫秒TemplateEncoder,相差10倍。

有关HTTP-RPCTemplateEncoder和的更多信息ElementAdapter,请参见项目README。