使用相应的代码替换xml文档中的特殊字符,例如 - 和 - 等

时间:2014-02-03 09:24:42

标签: java xml regex templates xslt

我希望替换像&amp ;;这样的特殊字符。 ndash的;和& MDASH;在xml文档中出现相应的代码,如& #150;等

我有一个包含几个特殊字符的输入xml文档

 <?xml version="1.0"?>
  <!DOCTYPE BOOK SYSTEM "bookfull.dtd">
<BOOK> 
  <P>The war was between1890&ndash;1900
   <AF>something&mdash;something else</AF>
</P>
</BOOK>

还有其他几个字符,如&amp; rsquo的;单引号

我的xslt代码如下

<?xml version="1.0" encoding="UTF-8" ?>
     <xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml">

<xsl:output method="html" omit-xml-declaration="yes" indent="yes" />
<xsl:strip-space elements="*" />


<xsl:param name="pDest"
    select="'file:///d:/LWW_Book_ePub_Transform/Epub_ZipCreation/XSLT_Transform/Output/'" />

<xsl:template-match="P">
<html>
<xsl:apply-templates/>
</html>
</xsl:template-match>

<xsl:template-match="AF">
.....
<xsl:apply-templates/>
.....
</xsl:template-match>

</xsl:stylesheet>

我的解析java代码如下(我正在使用saxon9。)

package com.xsltprocessor;

import java.io.File;
import java.io.FileInputStream;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Source;
import javax.xml.transform.Templates;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

import org.w3c.dom.Document;

public class ParseUsingSAX {

public ParseUsingSAX() {
}

public void parseBookContent(String xsltFile) {
    try {


        //File inputXml = new File("D:\\data\\myxml.0f");
        File xslt = new File(xsltFile);

        TransformerFactory factory = TransformerFactory.newInstance();
        Templates template = factory.newTemplates(new StreamSource(new FileInputStream(xslt)));
        Transformer xformer = template.newTransformer();
        Source source = new StreamSource(new FileInputStream(inputXml));
        StreamResult result = new StreamResult();
        xformer.transform(source,result);           
        System.out.println("DONE");
    }
    catch (Exception ex) {
        // TODO Auto-generated catch block
        ex.printStackTrace();
        System.out.println("IO exception: " + ex.getMessage());
    }
}

}

我在转换后获得输出

<html>
The war was between1890&ndash;1900
</html>

预期产出

<html>
The war was between1890&#150;1900
</html>

2 个答案:

答案 0 :(得分:1)

使用控制输出序列化的xsl:character-map元素。

<xsl:character-map name="dashes">
    <xsl:output-character character="&ndash;" string="&#150;"/>
</xsl:character-map>

您还必须声明

<xsl:output use-character-maps="dashes"/>

作为确保使用字符映射的顶级元素。

正如我在评论中提到的,&ndash;是一个需要在XSLT中声明的HTML命名实体。参见例如this讨论了更多细节。

嵌入到您显示的样式表中(这会输出虚拟字符串“MDASH”和“NDASH” - 仅用于说明):

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE stylesheet [
<!ENTITY ndash  "&#x2013;" >
<!ENTITY mdash  "&#x2014;" >
]>
<xsl:stylesheet version="2.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns="http://www.w3.org/1999/xhtml">

  <xsl:output method="html" omit-xml-declaration="yes" indent="yes" />
  <xsl:output use-character-maps="dashes"/>

  <xsl:strip-space elements="*" />

  <xsl:character-map name="dashes">
    <xsl:output-character character="&ndash;" string="NDASH"/>
    <xsl:output-character character="&mdash;" string="MDASH"/>
  </xsl:character-map>

  <xsl:param name="pDest"
    select="'file:///d:/LWW_Book_ePub_Transform/Epub_ZipCreation/XSLT_Transform/Output/'" />

  <xsl:template match="BOOK">
    <html>
      <xsl:apply-templates/>
    </html>
  </xsl:template>

  <xsl:template match="AF|P">
    <xsl:copy>
      <xsl:value-of select="."/>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

请注意,这对使用xsl:result-document生成的输出没有影响(因为您没有显示整个样式表)。有关角色地图的更多信息,请参阅a previous answer of mine和官方recommendation

答案 1 :(得分:1)

<!DOCTYPE BOOK SYSTEM "bookfull.dtd">中提到的DTD将包含所使用的实体引用(如&ndash;)或者它是错误的(或者我认为输入XML在尝试使用实体时可能出错了应该可以使用)。

如果包含它们,则需要设置XSLT处理器以根据其DTD验证文档。 (我不知道如何在你的情况下这样做,因为我知道问题的XSLT部分,但不知道如何在Java中使用XSLT的具体细节。)

如果没有,你将不得不修复它。

获取http://www.w3.org/2003/entities/2007/w3centities-f.ent的副本(虽然它只能引用该URI本身,如果不这样做,W3会更喜欢,并且你不会以这种方式获得更好的性能。)

然后创建自己的bookfull.dtd,其中包括:

<!ENTITY % w3centities-f PUBLIC "-//W3C//ENTITIES Combined Set//EN//XML"
    "w3centities-f.ent">
%w3centities-f;

或者,它直接在DTD中包含该文件的内容。

现在,在解释输入文档时,可以解析实体引用。例如,上面的&ndash;定义为:

<!ENTITY ndash            "&#x02013;" ><!--EN DASH -->

或者换句话说; “只要出现&ndash;,请将其替换为”。

这在XSLT样式表运行之前的XML解析步骤中发生,因此就XSLT而言,它收到的内容包含,而不是&ndash;,并将其视为这样