使用XSLT转换XML时保留实体引用?

前端之家收集整理的这篇文章主要介绍了使用XSLT转换XML时保留实体引用?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
在使用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>

输出应该看起来像输入(减去现在的doctype声明):

<doc>
  <text>Hello &so;!</text>
  <text>&question;</text>
</doc>

我希望我不需要用& amp;替换所有的&符号来预处理输入. (比较& amp;问题;)然后通过替换所有& amp; amp后处理输出与&amp ;.

也许这是处理器特定的?我正在使用Saxon 9.

谢谢!

如果您知道将使用哪些实体以及如何定义它们,您可以执行以下操作(相当原始且容易出错,但仍然比没有更好):
<xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:xs="http://www.w3.org/2001/XMLSchema"
 xmlns:my="my:my">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:character-map name="mapEntities">
  <xsl:output-character character="&amp;" string="&amp;"/>
 </xsl:character-map>

 <xsl:variable name="vEntities" select=
 "'stackoverflow','How can I preserve the entity reference when transforming with XSLT\?\?'
 "/>

 <xsl:variable name="vReplacements" select=
 "'&amp;so;','&amp;question;'"/>

 <xsl:template match="node()|@*">
  <xsl:copy>
   <xsl:apply-templates select="node()|@*"/>
  </xsl:copy>
 </xsl:template>

 <xsl:template match="/">
  <xsl:text disable-output-escaping="yes"><![CDATA[<!DOCTYPE doc [ <!ENTITY so "stackoverflow">
<!ENTITY question
"How can I preserve the entity reference when transforming with XSLT??"> ]>
]]>
  </xsl:text>

  <xsl:apply-templates/>
 </xsl:template>

 <xsl:template match="text()">
  <xsl:value-of select=
  "my:multiReplace(.,$vEntities,$vReplacements,count($vEntities)
                   )
  " disable-output-escaping="yes"/>
 </xsl:template>

 <xsl:function name="my:multiReplace">
  <xsl:param name="pText" as="xs:string"/>
  <xsl:param name="pEnts" as="xs:string*"/>
  <xsl:param name="pReps" as="xs:string*"/>
  <xsl:param name="pCount" as="xs:integer"/>

  <xsl:sequence select=
  "if($pCount > 0)
     then
      my:multiReplace(replace($pText,$pEnts[1],$pReps[1]
                              ),subsequence($pEnts,2),subsequence($pReps,$pCount -1
                      )
      else
       $pText
  "/>
 </xsl:function>
</xsl:stylesheet>

当应用于提供的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>

请注意:

>必须转义替换中的特殊(RegEx)字符.>我们需要解决DOE,这是不推荐的,因为它违反了XSLT架构和处理模型的原则 – 换句话说,这个解决方案是一个讨厌的黑客.

原文链接:https://www.f2er.com/xml/292625.html

猜你在找的XML相关文章