xslt嵌套强调标签转换

时间:2013-04-30 19:25:58

标签: html xml xslt

我的某些文件存在问题,可以使用帮助解决它。我正在从html转换为xml。有时我自己有<b><u><i>标记,我使用

<xsl:template match="i">
<emphasis italic="yes">
<xsl:apply-templates select="*|@*|text()"/>
</emphasis>
</xsl:template>

或粗体表示b和下划线表示你。

有时我在<u>

中有一个嵌套的<b>

对于这些我使用

<xsl:template match="b/u">
<xsl:apply-templates select="*|@*|text()"/>
</xsl:template>

这是为了摆脱u

<xsl:template match="b[u]">
<emphasis bold="yes" underline="yes">
<xsl:apply-templates select="*|@*|text()"/>
</emphasis>
</xsl:template>

这是为了转换b后跟u

现在我的问题是当u嵌套在i嵌套在b时,该怎么做。这是什么代码?

2 个答案:

答案 0 :(得分:0)

要回答您的直接问题,要匹配嵌套在u ib的{​​{1}},您可以这样做

<xsl:template match="b/i/u">

您还需要模板来处理父bi

<xsl:template match="b[i/u]">

<xsl:template match=b/i[u]">

但是大概你想要处理以任何顺序嵌套的元素?每个可能的permuation的编码模板将变得非常混乱,您还必须担心匹配相同元素的两个模板。

相反,试试这个稍微灵活的XSLT,虽然不是特别优雅

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:output method="xml" indent="yes"/>

   <xsl:template match="i[parent::b|parent::u]" name="italic">
      <xsl:attribute name="italic">yes</xsl:attribute>
      <xsl:apply-templates select="*|@*|text()"/>
   </xsl:template>

   <xsl:template match="b[parent::i|parent::u]" name="bold">
      <xsl:attribute name="bold">yes</xsl:attribute>
      <xsl:apply-templates select="*|@*|text()"/>
   </xsl:template>

   <xsl:template match="u[parent::b|parent::i]" name="underline">
      <xsl:attribute name="underline">yes</xsl:attribute>
      <xsl:apply-templates select="*|@*|text()"/>
   </xsl:template>   

   <xsl:template match="*[self::b|self::i|self::u][not(parent::b)][not(parent::i)][not(parent::u)]">
      <emphasis>
         <xsl:choose>
            <xsl:when test="self::b">
            <xsl:call-template name="bold"/>
            </xsl:when>
            <xsl:when test="self::i">
            <xsl:call-template name="italic"/>
            </xsl:when>
            <xsl:when test="self::u">
            <xsl:call-template name="underline"/>
            </xsl:when>
         </xsl:choose>
      </emphasis>
   </xsl:template>

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

我们的想法是,您拥有与ibu元素匹配的模板,这些元素具有其他元素作为父元素。在这种情况下,您只需输出相关属性。

您还拥有与最高ibu元素匹配的主模板(即没有其他元素作为父元素的元素),您输出重点元素。请注意,使用命名模板更简单,以避免某些代码重复。

将其应用于以下XML

<test>
   <b>bold</b>
   <i>Italic</i>
   <b><i>bold Italic</i></b>
   <u><b><i>bold Italic underline</i></b></u>
</test>

以下是输出

<test>
   <emphasis bold="yes">bold</emphasis>
   <emphasis italic="yes">Italic</emphasis>
   <emphasis bold="yes" italic="yes">bold Italic</emphasis>
   <emphasis underline="yes" bold="yes" italic="yes">bold Italic underline</emphasis>
</test>

答案 1 :(得分:0)

这是一个简单而简短的解决方案:只有两个模板,没有明确的条件指令

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:my="my:my" exclude-result-prefixes="my">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <my:names>
   <n short="b">bold</n>
   <n short="i">italic</n>
   <n short="u">underline</n>
 </my:names>

 <xsl:variable name="vNames" select="document('')/*/my:names/*"/>

 <xsl:template match=
  "node()[not(contains('+b+i+u+', concat('+',name(),'+')))]
         /*[contains('+b+i+u+', concat('+',name(),'+'))]
  ">
   <emphasis>
      <xsl:apply-templates select="." mode="emph"/>
   </emphasis>
  </xsl:template>

 <xsl:template mode="emph"
   match="*[contains('+b+i+u+', concat('+',name(),'+'))]">
   <xsl:attribute name="{$vNames[@short=name(current())]}">yes</xsl:attribute>
   <xsl:apply-templates select="node()" mode="emph"/>
 </xsl:template>
</xsl:stylesheet>

对以下XML文档应用此转换时:

<test>
   <b>bold</b>
   <i>Italic</i>
   <b><i>bold Italic</i></b>
   <u><b><i>bold Italic underline</i></b></u>
</test>

产生了想要的正确结果:

<emphasis bold="yes">bold</emphasis>
<emphasis italic="yes">Italic</emphasis>
<emphasis bold="yes" italic="yes">bold Italic</emphasis>
<emphasis underline="yes" bold="yes" italic="yes">bold Italic underline</emphasis>