这是一个通用的XSLT 1.0问题,我需要知道这个问题才能编写XSLT语句来处理docbook xml文件。在我的docbook XML中,我试图在XSLT 1.0中编写一个复合的xpath语句,该语句表示为html输出中的p标签硬编码一个新属性“ class =” play“。

我希望对没有这些属性的每个<para>标签执行此操作


角色=“正常播放段”和
角色=“ no-indent” AND
“ role =” line-verse“


这是我的XML来源:

<chapter xmlns="http://docbook.org/ns/docbook"
 xmlns:xlink="http://www.w3.org/1999/xlink"
        version="5.0" xml:id="play">
  <title> Hamlet </title>

    <para role="no-indent"> SPHINX. Do you think about it very much?</para>
    <para role="normal-play-para"> INTERVIEWER. I do so say. </para>
    <para>SPHINX. Hello </para>
    <para> INTERVIEWER. dddddWhy I do so say. </para>
    <para> SPHINX. Yes. </para>
    <para role="line-verse"> Cosmologists have theorized or guessed</para>
</chapter>


在Docbook XSLT处理它之后,我希望HTML输出看起来像这样:

<html>
<body>
<p class="no-indent">SPHINX. Do you think about it very much? much. </p>
 <p class="normal-play-para"> INTERVIEWER. I do so say. </p>
   <p class="play">SPHINX. Hello </p>
   <p class="play">INTERVIEWER. dddddWhy I do so say. </p>
   <p class="play">SPHINX. Yes.  </p>
 <p class="line-verse"> Cosmologists have theorized or guessed</p>
</body>
<html>


docbook xslt有2种工作机制,您实际上并不需要了解。

首先,在<para role="">元素中,角色的值更改为p的类。这是默认行为。
其次,我正在使用一种特殊模式将"class='play'"硬编码为p标签。

<xsl:template match="d:chapter[@xml:id = 'play']/d:para" mode="class.attribute" >
  <xsl:param name="class" select="local-name(.)"/>
  <xsl:attribute name="class">play</xsl:attribute>
</xsl:template>


但是,我只希望在不存在其他属性和值的情况下对class =“ play”进行硬编码。我可以修改上面的语句以排除所有具有属性role =“ line-verse”的para标签:

  <xsl:template match="d:chapter[@xml:id = 'play']/d:para[@role != 'line-verse']" mode="class.attribute" >
    <xsl:param name="class" select="local-name(.)"/>
    <xsl:attribute name="class">play</xsl:attribute>
  </xsl:template>


但我还需要更多。我不仅要排除role =“ line-verse”,还要排除role =“ no-indent”和role =“ normal-play-para”。

因此,我必须在match属性中更改xpath语句的值,以便它排除三个属性值。我还不知道该怎么做。有人知道吗谢谢。

关于答案的更新:

首先,我要感谢大家花时间了解我的问题并提出答案。我应该提及的是,我仍然是这方面的新手,而且我的问题有点不公平,因为我使用的是一些复杂的Docbook XSL。因此,我需要一个不会与Docbook XSL样式表发生冲突的答案。另外,我意识到您编写的转换可能是生成html输出的完美答案,如果我也没有导入docbook xsl。

在这里我选择为“最佳”的答案可能不是最优雅的,而仅仅是在我导入epub3 docbook-ns样式表的情况下对我有用的答案。因此,Rishe先生的一句话答案实际上确实可以满足我的要求,即使它并不那么优雅。

我真的不知道我开始时的自定义操作是怎么回事:

<xsl:template match="d:chapter[@xml:id = 'play']/d:para" mode="class.attribute" >
  <xsl:param name="class" select="local-name(.)"/>
  <xsl:attribute name="class">play</xsl:attribute>
</xsl:template>


我所知道的是它正在调用<xsl:template name="generate.class.attribute">,它在这里找到。 http://50.56.245.89/xsl-ns/xhtml-1_1/html.xsl

另一件事。 Dimitre Novatchev的2个答案似乎很有效。顺便说一句,您忘记了包含<xsl:param name="class" select="local-name(.)"/>语句(很容易解决),该解决方案有效。

但是,迪米特雷,我还有另一个问题。您给的第二个答案是使用的变量,看起来很简单且实用。如果尝试,我的Saxon 6.5解析器将给出验证错误。 (E [Saxon6.5.5] xsl:template中的匹配模式可能不包含对变量的引用)。也许像打字错误一样简单。但是是否有可能在XSLT 1.0模板匹配中不允许使用变量?

最佳答案

您可以尝试一下:

<!-- Special handling for paras with one of the three roles -->
<xsl:template
  match="d:chapter[@xml:id = 'play']/d:para[@role = 'line-verse' or @role = 'normal-play-para' or @role - 'line-indent']"
  mode="class.attribute" >
  <xsl:attribute name="class">
      <xsl:value-of select="@role" />
  </xsl:attribute>
</xsl:template>

<!-- Other paras get the default class "play" -->
<xsl:template match="d:chapter[@xml:id = 'play']/d:para" mode="class.attribute">
  <xsl:attribute name="class">play</xsl:attribute>
</xsl:template>


进一步的步骤是在调用这些模板的模板中包含<xsl:attribute>,而在class.attribute模板本身中仅具有所需的值。像这样:

<xsl:template match="d:chapter[@xml:id = 'play']/d:para">
    <p>
      <xsl:attribute name="class">
         <xsl:apply-templates select="." mode="class.attribute" />
      </xsl:attribute>
    ...
    </p>
</xsl:template>

<!-- Special handling for paras with one of the three roles -->
<xsl:template
  match="d:chapter[@xml:id = 'play']/d:para[@role = 'line-verse' or @role = 'normal-play-para' or @role - 'line-indent']"
  mode="class.attribute" >
      <xsl:value-of select="@role" />
</xsl:template>

<!-- Other paras get the default class "play" -->
<xsl:template match="d:chapter[@xml:id = 'play']/d:para" mode="class.attribute">
  <xsl:text>play</xsl:text>
</xsl:template>


要专门回答您的原始问题,如果您确实需要一个专门匹配para且没有这些@role值之一的模板,则可以在此XPath上进行匹配:

d:chapter[@xml:id = 'play']/d:para[not(@role = 'line-verse' or @role = 'normal-play-para' or @role - 'line-indent')]


但是我认为我上面介绍的方法(将这些角色视为特例,将其他所有角色视为默认情况)是更好的方法。

10-07 18:09