使用XSLT保留特殊字符作为输出



即使在XSLT转换之后,我面临的问题是关于特殊字符的保留。我的源XHTML文件包含几个特殊字符,例如 —’;在XSLT变换时被忽略。

我尝试了这样的各种答案。

如果我要手动将特殊字符的值更改为其相应的Unicode表示形式,则该字符保留在输出中。

例如将 更改为 ,它会导致输出中的一个空间。请参考以下一些示例文档:

源XHTML:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:text="http://giraffe.wkle.com/text" xmlns:epub="http://www.idpf.org/2007/ops">
    <body>
        <div class="section" id="section_1">
            <p id="para_1" class="para">Content&nbsp;of&nbsp;paragraph&mdash;1.</p>
            <p id="para_2" class="para">Content&nbsp;of&nbsp;paragraph&mdash;2.</p>
        </div>
    </body>
</html>

XSL模板:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xsl:output method="xml" indent="yes"/>
    <xsl:template match="node()|@*" name="identity">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*" />
        </xsl:copy>
    </xsl:template>
    <xsl:template match="*[local-name()='p']/text()">
        <xsl:copy-of select="."/>
    </xsl:template>
</xsl:stylesheet>

预期输出:

<?xml version="1.0" encoding="UTF-8"?>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:epub="http://www.idpf.org/2007/ops" xmlns:text="http://giraffe.wkle.com/text">
    <body>
        <div class="section" id="section_1">
            <p class="para" id="para_1">Content of paragraph—1.</p>
            <p class="para" id="para_2">Content of paragraph—2.</p>
        </div>
    </body>
</html>

实际输出:

<?xml version="1.0" encoding="UTF-8"?>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:epub="http://www.idpf.org/2007/ops" xmlns:text="http://giraffe.wkle.com/text">
    <body>
        <div class="section" id="section_1">
            <p class="para" id="para_1">Contentofparagraph1.</p>
            <p class="para" id="para_2">Contentofparagraph2.</p>
        </div>
    </body>
</html>

限制:

  1. 我无法访问修改源XHTML内容或其DTD。
  2. XSLT的版本为1.0。

请让我知道是否有任何方法可以使用其Unicode值转换特殊字符并将其保留在我的输出XML文档中。

更新:

我使用此Java代码来调用转换:

public class XSLTUtil {
    public static String processXHTML(String sourceFileName, String outputXhtml, String xslFilePath) throws ParserConfigurationException, SAXException, IOException, TransformerException {
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        DocumentBuilder docbuilder = factory.newDocumentBuilder();
        Document doc = docbuilder.parse(new FileInputStream(sourceFileName));
        FileOutputStream fos = null;
        FileInputStream fis = null;
        try {
            fos = new FileOutputStream(outputXhtml);
            fis = new FileInputStream(xslFilePath);
            TransformerFactory transformfactory = TransformerFactory.newInstance();
            Templates xsl = transformfactory.newTemplates(new StreamSource(fis));
            Transformer transformer = xsl.newTransformer();
            transformer.transform(new DOMSource(doc.getDocumentElement()),new StreamResult(fos));
            return outputXhtml;
        } finally {
            if(fos != null) {
                fos.close();
            }
            if(fis != null) {
                fis.close();
            }
        }
    }
    public static void main(String args[]){
        String sourceFileName = "C:\source.xhtml";
        String outputXhtml = "C:\output.xhtml";
        String xslFilePath = "C:\xslTemplate.xsl";
        String result = "-1";
        try {
            result = processXHTML(sourceFileName, outputXhtml, xslFilePath);
        } catch (ParserConfigurationException e) {
            e.printStackTrace();
        } catch (SAXException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (TransformerException e) {
            e.printStackTrace();
        }
        System.out.println("Result : "+ result);
    }
}

apache commons lang3 stringescaputils 的解决方案。需要图书馆:

    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-lang3</artifactId>
        <version>3.0</version>
    </dependency>

首先阅读内容,然后将所有实体替换为真实文本。

public static String processXHTML(String sourceFileName, String outputXhtml,
        String xslFilePath) throws ParserConfigurationException, SAXException, IOException,
        TransformerException {
    Charset charset = StandardCharsets.UTF_8;
    Path path = Paths.get(sourceFileName);
    String source = new String(Files.readAllBytes(path), charset);
    source = source.replaceAll("\&(amp|lt|gt|quot);", "u0001$1;");
    source = StringEscapeUtils.unescapeHtml4(source);
    source = source.replace('u0001', '&');
    byte[] bytes = source.getBytes(charset);
    ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    DocumentBuilder docbuilder = factory.newDocumentBuilder();
    docbuilder.setEntityResolver(new EntityResolver() {
        @Override
        public InputSource resolveEntity(String publicId, String systemId)
                    throws SAXException, IOException {
            System.out.printf("resolveEntity PUBLIC %s SYSTEM %s%n", publicId, systemId);
            return new InputSource(new StringReader(""));
        }
    });
    //Document doc = docbuilder.parse(new FileInputStream(sourceFileName));
    Document doc = docbuilder.parse(bais);

我跳过XML实体。

我已经短暂地束缚了实体,因为阅读和处理实体(网上)需要很长时间。似乎您已经安装了类似的东西,因为没有更换实体。

在解决方案中返回null以查看递归加载的DTD。

另外,您可以安装 XML目录,HTML Entity DTD的本地缓存,其中有一些。

我会摆脱DOM代码。当您想要的只是将其转换为其他东西时,创建DOM是笨拙且效率低下的。如果您提供流媒体或萨克斯苏里斯,撒克逊人和Xalan都可以更快地运行,并让他们决定自己的树代表。使用撒克逊人,可以更快地使用5-10倍,并且将使用更少的内存。

我不知道为什么DOM失去实体参考。您已经提供了有关使用哪个XSLT处理器的相互矛盾的信息,因此调查并不容易,但是因为DOM数据模型与XSLT/XPATH数据模型(尤其是在对实体扩展的处理中)的不同之处应该摆脱DOM解决它。

[对问题的较早版本的回答]

考虑使用Andrew Welch的Lexev实用程序。它基本上是对XML进行预处理,以将实体引用转换为将通过XML解析保留的东西,然后后处理转换结果将实体参考放回。

http://andrewjwelch.com/lexev/

最新更新