0

我的环境是使用 XSLT 2.0 的 SAXON(昨晚构建)。我真正的问题是 XML 文档规范不是最佳的,并且在某种程度上,我的问题与修复/解决该设计问题有关。

我有一个节点类型 ( <weaponmodesdata>),其中所有直接子节点都是 | 分隔的 1 个或多个元素的字符串列表(相同的每个子节点<weaponmodesdata>将具有相同的长度)。我需要检查所代表的各种模式并将它们“解开”以分离项目列表(以纯文本形式),而不是将它们全部融合在一起。

不幸的是,现在我变得非常固执

XPTY0020: Required item type of the context item for the child axis is node(); supplied
value has item type xs:string

在我传递需要拆分为我的小模板的节点的行上出现错误。

目前我有

  <xsl:template match="trait" mode="attack">

    <xsl:for-each select="tokenize(weaponmodesdata/mode, '\|')">
      <xsl:variable name="count" select="position()"/>
      <xsl:value-of select="name"/><xsl:text> - </xsl:text>
      <xsl:call-template name="split_weaponmode">
        <xsl:with-param name="source" select="weaponmodesdata/damage"/>
        <xsl:with-param name="item" select="$count"/>
      </xsl:call-template>
      <xsl:text> </xsl:text>
      <xsl:call-template name="split_weaponmode">
        <xsl:with-param name="source" select="weaponmodesdata/damtype"/>
        <xsl:with-param name="item" select="$count"/>
      </xsl:call-template>
      <!-- more will go here eventually --> 
      <xsl:text>.&#xD;&#xA;</xsl:text>
    </xsl:for-each>
  </xsl:template>

  <xsl:template name="split_weaponmode">
    <xsl:param name="source"/>
    <xsl:param name="item"/>
    <xsl:variable name="parts" select="tokenize($source, '\|')"/>
    <xsl:for-each select="$parts">
      <xsl:if test="position() = $item">
        <xsl:value-of select="."/>
      </xsl:if>
    </xsl:for-each>
  </xsl:template>

与我的问题相关的示例 XML 子树:

<character>
    <trait id="1">
        <name>Spear</name>
        <weaponmodesdata>
            <mode>1H Thrust|2H Thrust|Thrown</mode>
            <damage>thr+2|thr+3|thr+3</damage>
            <damtype>imp|imp|imp</damtype>
        </weaponmodesdata>
    </trait>
    <trait id="2">
        <name>Broadsword</name>
        <weaponmodesdata>
            <mode>1H Thrust|1H Swing</mode>
            <damage>thr+1|sw+2</damage>
            <damtype>imp|cut</damtype>
        </weaponmodesdata>
    </trait>
</character>

示例所需的输出:

Spear - 1H Thrust; thr+2 imp.
Spear - 2H Thrust; thr+3 imp.
Spear - Thrown; thr+3 imp.
Broadsword - 1H Thrust; thr+1 imp.
Broadsword - 1H Swing; sw+2 cut.
4

1 回答 1

2

您的代码的一个问题(导致错误消息的问题)是您for-each对一系列字符串值进行操作(即在for-each正文中,上下文项是字符串值),但是您有像weaponmodesdata/damage这样的相对 XPath 表达式需要上下文节点说得通。因此,您需要使用外部的变量for-each来存储您的上下文节点。

但我认为您可以将代码简化为

<xsl:stylesheet
  version="2.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  exclude-result-prefixes="xs">

<xsl:output method="text"/>
<xsl:strip-space elements="*"/>

<xsl:template match="trait">
  <xsl:variable name="this" select="."/>
  <xsl:variable name="count" select="count(tokenize(weaponmodesdata/*[1], '\|'))"/>
  <xsl:for-each-group select="weaponmodesdata/*/tokenize(., '\|')" group-by="position() mod $count">
    <xsl:value-of select="$this/name"/>
    <xsl:text> - </xsl:text>
    <xsl:value-of select="current-group()"/>
    <xsl:text>.&#10;</xsl:text>
  </xsl:for-each-group>

</xsl:template>

</xsl:stylesheet>

如果您想坚持调用模板的方法,请确保使用 eg 存储模板的上下文节点,<xsl:variable name="this" select="."/>以便您可以在for-each迭代字符串项的过程中访问它。

于 2013-07-15T08:52:03.307 回答