使用XSLT转换XML时保留实体引用?
使用XSLT(2.0)转换XML时如何保留实体引用?对于我尝试过的所有处理器,默认情况下会解析实体。我可以使用使用XSLT转换XML时保留实体引用?,xml,xslt,xslt-2.0,Xml,Xslt,Xslt 2.0,使用XSLT(2.0)转换XML时如何保留实体引用?对于我尝试过的所有处理器,默认情况下会解析实体。我可以使用xsl:character-map来处理字符实体,但是文本实体呢 例如,此XML: <!DOCTYPE doc [ <!ENTITY so "stackoverflow"> <!ENTITY question "How can I preserve the entity reference when transforming with XSLT??"> ]&
xsl:character-map
来处理字符实体,但是文本实体呢
例如,此XML:
<!DOCTYPE doc [
<!ENTITY so "stackoverflow">
<!ENTITY question "How can I preserve the entity reference when transforming with XSLT??">
]>
<doc>
<text>Hello &so;!</text>
<text>&question;</text>
</doc>
]>
你好;!
&问题,;
使用以下XSLT进行转换:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
生成以下输出:
<doc>
<text>Hello stackoverflow!</text>
<text>How can I preserve the entity reference when transforming with XSLT??</text>
</doc>
你好!
使用XSLT转换时如何保留实体引用??
输出应该与输入类似(暂时不包括doctype声明):
你好;!
&问题,;
我希望我不必通过用替换所有的符号来预处理输入编码>(如&;question;
),然后通过替换所有&带有和的code>
也许这是特定于处理器的?我用的是萨克森9
谢谢 如果您知道将使用哪些实体以及它们是如何定义的,您可以执行以下操作(非常简单且容易出错,但总比没有好):
]>
]]>
应用于提供的XML文档时:
<!DOCTYPE doc [ <!ENTITY so "stackoverflow">
<!ENTITY question
"How can I preserve the entity reference when transforming with XSLT??"> ]>
<doc>
<text>Hello &so;!</text>
<text>&question;</text>
</doc>
<!DOCTYPE doc [ <!ENTITY so "stackoverflow">
<!ENTITY question
"How can I preserve the entity reference when transforming with XSLT??"> ]>
<doc>
<text>Hello &so;!</text>
<text>&question;</text>
</doc>
]>
你好;!
&问题,;
产生所需结果:
<!DOCTYPE doc [ <!ENTITY so "stackoverflow">
<!ENTITY question
"How can I preserve the entity reference when transforming with XSLT??"> ]>
<doc>
<text>Hello &so;!</text>
<text>&question;</text>
</doc>
<!DOCTYPE doc [ <!ENTITY so "stackoverflow">
<!ENTITY question
"How can I preserve the entity reference when transforming with XSLT??"> ]>
<doc>
<text>Hello &so;!</text>
<text>&question;</text>
</doc>
]>
你好;!
&问题,;
注意事项:
替换中的特殊(正则表达式)字符必须转义
我们需要解决DOE,这是不推荐的,因为它违反了XSLT体系结构和处理模型的原则——换句话说,这个解决方案是一个令人讨厌的黑客
如果您使用XSLT2.0处理器的Java实现(如Saxon 9 Java),您可能需要检查是否有帮助,您可以使用实体和字符引用对XML进行预处理,以便将它们标记为XML元素,然后根据需要进行转换。如果使用S1000D之类的东西,这可能是一个特别麻烦的问题。它使用实体和@boardno属性链接到图形。这是对其SGML根源的回溯
由于这种自动实体扩展行为是正确的,但不受欢迎,因此当使用S1000D作为输入时,我经常不得不返回到sed、awk和批处理脚本等工具来管理某些数据分析任务
对于即将推出的XSLT规范之一,这将是一个伟大的改变建议,即兼容处理器接受一个运行时参数,该参数可以打开和关闭实体扩展。您可以使用DOM LS解析器将“entities”参数设置为true,从而在文档中保留EntityReference节点。
规范说默认值为true,但根据解析器的不同,它可能为false,请注意这一点
要加载Xerce,请执行以下操作:
DOMImplementationLS domImpl = new org.apache.xerces.dom.CoreDOMImplementationImpl();
您也可以按如下方式使用注册表,但我更愿意按上述方式硬编码我想要的实现:
DOMImplementationRegistry registry = DOMImplementationRegistry.newInstance();
DOMImplementationLS domImpl = (DOMImplementationLS) registry.getDOMImplementation("XML 3.0 LS 3.0");
然后,要加载您的文档:
// XML parser with XSD schema
LSParser parser = domImpl.createLSParser(DOMImplementationLS.MODE_SYNCHRONOUS, "http://www.w3.org/2001/XMLSchema");
DOMConfiguration config = parser.getDomConfig();
config.setParameter("entities", true);
LSInput input = impl.createLSInput();
Document lDoc = parser.parse(your XML stream);
然后,您的XML实体不会在DOM中展开
然后,由于SAXON不处理未扩展的实体(“DOM!5中不支持的节点类型”错误),因此不能使用net.sf.SAXON.xpath.XPathFactoryImpl
,必须使用XPathFactory.newInstance()设置Xerces的默认XPathFactory。我使用此解决方案,它工作正常:
<xsl:variable name="prolog" select="substring-before(unparsed-text(document-uri(.)),'<root')"/>
<xsl:template match="/">
<xsl:value-of select="$prolog" disable-output-escaping="yes"/>
<xsl:apply-templates/>
</xsl:template>
问得好,+1。请求的处理几乎不可能用XSLT完成,我不建议经常使用我的答案。非常感谢Dimitre。我很害怕。不幸的是,我不知道正在使用什么实体。我想我会坚持这个项目的OmniMark。不过你的回答很有帮助,我很感谢你抽出时间+1和answer acceptedI我主要处理ATA iSpec 2200,也曾处理过S1000D,因此我完全了解您的意思。我尝试过使用这种方法,但当将文档用作DOM源时,您会得到[致命错误]:xxx:yyy:字符引用“
您能提供更多关于源代码、XML输入的详细信息吗?我已经没有了。实际上,我找到了另一种处理需求的方法,将实体数据保存在一个属性中,而该属性不会被翻译。我没有尝试过这种方法,但它看起来只会保留序言;实体引用仍将扩展。我可以看到使用xsl:analyze string
来分析prolog并建立键/值对的结构(或3.0中的映射),然后在处理过程中替换它们。也许有一天我会试试这个主意。为了真正解决这个问题,我最终编写了一个Omnimark程序,类似于另一个答案中提到的“lexev”java程序。