首页 文章

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

提问于
浏览
1

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

我尝试了各种答案,如thisthis .

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

对于例如将   更改为   ,会在输出中产生一个空格 . 请参考下面的一些示例文件:

Source 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 Template :

<?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>

Expected Output :

<?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>

Actual Output :

<?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>

Limitations :

  • 我无权修改源XHTML内容或其DTD .

  • XSLT的版本是1.0 .

如果有任何方法可以使用Unicode值转换特殊字符并将其保留在输出XML文档中,请告诉我 .

Update :

我使用这段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);
    }
}

3 回答

  • 0

    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实体 .

    我已经短接了EntityResolver,因为读取和处理实体(通过网络)需要很长时间 . 您似乎已经安装了类似的东西,因为实体没有被替换 .

    在resolveEntity中返回null以查看递归加载的DTD .

    或者,您可以安装 XML catalog ,HTML实体DTD的本地缓存,其中有一些 .

  • 0

    我会摆脱DOM代码 . 当你想要的只是将它转换成其他东西时创建一个DOM是笨拙和低效的 . 如果您提供StreamSource或SAXSource并让他们决定自己的树表示,Saxon和Xalan都会运行得更快 . 使用Saxon,速度可提高5到10倍,并且使用的内存将减少很多 .

    我不知道DOM为什么会丢失实体引用 . 您已经提供了有关您正在使用哪个XSLT处理器的相互矛盾的信息,因此调查并不容易,但是因为DOM数据模型与XSLT / XPath数据模型不同(特别是在处理实体扩展时),应该删除DOM解决这个问题 .

  • 1

    [对早期版本问题的过时答案]

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

    http://andrewjwelch.com/lexev/

相关问题