Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/xslt/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用XSLT转换XML时保留实体引用?_Xml_Xslt_Xslt 2.0 - Fatal编程技术网

使用XSLT转换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??"> ]&

使用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??">
]>
<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(.)),'&lt;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程序。