我如何浏览HTML,然后使用XSLT进行转换?

时间:2014-12-30 07:07:09

标签: html xml xslt escaping

我是XSLT的新手,我有一个大型的XML文档,我试图将其转换为ICML(Adobe InDesign使用的XML变体)。我正在使用的源文档的相关部分看起来像这样:

<BiographicalNote>
 &lt;p&gt;This text includes escaped HTML entities.&lt;/p&gt;
</BiographicalNote>

XML本身很好,但它包含的HTML是转义的。

以下是我需要最终产品的粗略示例:

<ParagraphStyleRange>
 <CharacterStyleRange>
  <Content>
   This text includes escaped HTML entities.
  </Content>
 </CharacterStyleRange>
</ParagraphStyleRange>

我可以将<BiographicalNote>转换为<ParagraphStyleRange><CharacterStyleRange><Content>没有问题,但是转义的实体正在困扰我。我似乎无法删除<p>代码。

一些重要的考虑因素:

  • 源文档的HTML部分是由各种不同熟悉HTML的人编写的,并不总是很好地形成。取消整个源文档不是一个选项,因为它在运行XSLT时会导致解析器错误。
  • 源文档非常大(超过120,000行),因此查找和修复格式错误的HTML将非常不切实际且耗时。但是,在我实际需要的文件的特定部分中修复任何不良HTML(少于1%)更为可行。
  • 虽然我想删除<p>代码,但我需要保留大多数其他代码(<i><em><b>等等,以便我能够稍后将它们转换为<CharacterStyleRange>标记。
  • 我目前正在本地编写我的XSLT并使用终端(Mac)上的xsltproc运行转换。但最终,我将迁移到PHP系统并在服务器端运行转换。

我的基本模板如下所示:

<xsl:template match="BiographicalNote">
 <ParagraphStyleRange">
  <CharacterStyleRange>
   <Content>
   ...
   </Content>
  </CharacterStyleRange>
 </ParagraphStyleRange>
</xsl:template>

所以我需要弄清楚<Content>标签里面的内容。以下是我尝试过的内容:

<xsl:call-template name="DescriptionParser">
 <xsl:with-param name="DescriptionText"><xsl:value-of select="." disable-output-escaping="yes" /></xsl:with-param>
</xsl:call-template>

<xsl:template name="DescriptionParser">
 <xsl:param name="DescriptionText" />
 <xsl:copy-of select="exsl:node-set($DescriptionText)/p" />
</xsl:template>

<xsl:variable name="TaglineText"><xsl:value-of select="." disable-output-escaping="yes" /></xsl:variable>
<xsl:copy-of select="exsl:node-set($TaglineText)/p" />

这两个产生和空<Content>标记。但可疑的是,如果select="exsl:node-set($TaglineText)",它会按预期工作,并返回<p>This text includes escaped HTML entities.</p>所有未转义的内容。

此外,xsl:value-of(不返回任何内容)时,使用xsl:copy-of代替select="exsl:node-set($TaglineText)/p"没有任何区别;但是当select="exsl:node-set($TaglineText)"它返回原始转义 HTML。

由于某些原因,它似乎无法将<p>标记识别为节点,因此无法找到它。也许disable-output-escapingexsl:node-set并不合适?

有谁能告诉我如何让XSLT将<p>标签识别为节点,或者至少为什么它不起作用?我从其他StackOverflow主题中获得了大部分内容,但是我对这一点感到难过。

1 个答案:

答案 0 :(得分:2)

我不确定你的问题是什么。转义文本不是XML,不能作为XML处理。没有您可以选择的节点,因此您可以期望的最好结果是:

<Content>
<p>This text includes escaped HTML entities.</p>
</Content>

易于使用:

<Content>
    <xsl:value-of select="." disable-output-escaping="yes"/>
</Content>

如果要删除包装元素,则必须使用字符串函数执行此操作。如果您可以确定包装元素是<p>(或任何其他字符串长度为1的标记),您可以这样做:

<Content>
    <xsl:variable name="text" select="normalize-space(.)" />
    <xsl:value-of select="substring($text, 4, string-length($text) - 7)" disable-output-escaping="yes"/>
</Content>

或者,将此转换的结果保存到文件中,然后处理生成的文件。但是,这要求生成的文件是格式良好的XML文档 - 我知道您无法确定这一点。