English 中文(简体)
在申请项目组合没有匹配的情况下,我想打上一个指定模板。
原标题:I want to call a named template when apply-templates has no match
  • 时间:2012-05-15 20:41:38
  •  标签:
  • xslt

这是一种三维的例子,它涉及一个比较复杂的XSLT 1.0sheet,产生XSL-FO。

鉴于该投入XML,其中<Library>可能含有零或以上<Item> nodes,

<Library>
  <Item type="magazine" title="Rum"/>
  <Item type="book" title="Foo" author="Bar"/>
  <Item type="book" title="Fib" author="Fub"/>
  <Item type="magazine" title="Baz"/>
</Library>

而这一特别协定:

<xsl:template match="Library">
  <xsl:apply-templates select="Item[@type= Magazine ]/>
  <!-- How to call "NoMagazines" from here? -->
  <xsl:apply-templates select="Item[@type= Book ]/>
  <!-- How to call "NoBooks" from here? -->
</xsl:template>

<xsl:template match="Item[@type= book ]">
  <!-- do something with books -->
</xsl:template>

<xsl:template match="Item[@type= magazine ]">
  <!-- do something with magazines -->
</xsl:template>

<!-- how to call this template? -->
<xsl:template name="NoBooks">
  Sorry, No Books!
</xsl:template>

<!-- how to call this template? -->
<xsl:template name="NoMagazines">
  Sorry, No Magazines!
</xsl:template>

I want to produce the alternative Sorry, No [whatever]! message from the Library template when there are no Item nodes of the type [whatever].

So far, the only (ugly) solution I ve made is to select the child nodes by type into variables, test the variable, then either apply-templates if the variable contains nodes, or call the appropriate no match named template if the variable is empty (I m assuming test="$foo" will return false if no nodes are selected, I haven t tried it yet):

<xsl:template match="Library">
  <xsl:variable name="books" select="Items[@type= book ]"/>

  <xsl:choose>
    <xsl:when test="$books">
      <xsl:apply-templates select="$books"/>
    </xsl:when>
    <xsl:otherwise>
      <xsl:call-template name="NoBooks"/>
    </xsl:otherwise>
  </xsl:choose>

  <xsl:variable name="magazines" select="Items[@type= magazine ]"/>

  <xsl:choose>
    <xsl:when test="$magazines">
      <xsl:apply-templates select="$magazines"/>
    </xsl:when>
    <xsl:otherwise>
      <xsl:call-template name="NoMagazines"/>
    </xsl:otherwise>
  </xsl:choose>

</xsl:template>

我认为,这必须是异常低价竞标的设计模式(从GoF的角度来看),但我无法在网上找到任何例子。 任何建议都受到热烈欢迎!

最佳回答

也许像这种情况一样,作为季米特里斯解决办法的一种变量:

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

 <my:errorObjects>
  <noItem type="book">No Books</noItem>
  <noItem type="magazine">No Magazines</noItem>
 </my:errorObjects>

 <xsl:variable name="vErrorObjects" select=
  "document(  )/*/my:errorObjects"/>


 <xsl:template match="/*">
  <xsl:apply-templates select="(.|$vErrorObjects)/*[@type= magazine ]/>   
  <xsl:apply-templates select="(.|$vErrorObjects)/*[@type= book ]"/>
 </xsl:template>

 <xsl:template match="Item">
  <xsl:value-of select="concat( &#xA;Type:  , @type,  , title:  , @title)"/>
 </xsl:template>

 <xsl:template match="noItem">
  <xsl:if test="last() = 1">
    Sorry: <xsl:value-of select="."/>
  </xsl:if>
 </xsl:template>

</xsl:stylesheet>
问题回答

以下解决办法更为简明,但同样的原则。 它使用<代码>()功能确定是否存在杂志项目,如果没有,则使用<代码>NoMagazines模板。

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:template match="Library">
        <library>

            <!-- magazines -->
            <xsl:apply-templates select="Item[@type= magazine ]"/>
            <xsl:if test="count(Item[@type= magazine ]) = 0">
                <xsl:call-template name="NoMagazines"/>
            </xsl:if>

            <!-- books -->
            <!-- ... -->

        </library>      
    </xsl:template>

    <xsl:template match="Item[@type= magazine ]">
        <magazine>...</magazine>
    </xsl:template>

    <xsl:template name="NoMagazines">
        <noMagazines/>
    </xsl:template>

</xsl:stylesheet>

www.un.org/spanish/ecosoc 我将采取这种方式:

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

 <my:errorObjects>
  <noBook>No Books</noBook>
  <noMagazine>No Magazines</noMagazine>
 </my:errorObjects>

 <xsl:variable name="vErrorObjects" select=
  "document(  )/*/my:errorObjects"/>


 <xsl:template match="/*">
  <xsl:apply-templates select=
  "*[@type= magazine ]
  | $vErrorObjects[not(current()[*[@type= magazine ]])]/noMagazine"/>

  <xsl:apply-templates select=
  "*[@type= book ]
  | $vErrorObjects[not(current()[*[@type= book ]])]/noBook"/>
 </xsl:template>

 <xsl:template match="Item">
  <xsl:value-of select="concat( &#xA;Type:  , @type,  , title:  , @title)"/>
 </xsl:template>

 <xsl:template match="my:errorObjects/*">
  Sorry: <xsl:value-of select="."/>
 </xsl:template>
</xsl:stylesheet>

www.un.org/spanish/ecosoc 如果在规定的XML文件上适用这一转变:

<Library>
    <Item type="magazine" title="Rum"/>
    <Item type="book" title="Foo" author="Bar"/>
    <Item type="book" title="Fib" author="Fub"/>
    <Item type="magazine" title="Baz"/>
</Library>

<>亮度>(热)结果产生:

Type: magazine, title: Rum
Type: magazine, title: Baz
Type: book, title: Foo
Type: book, title: Fib

www.un.org/spanish/ecosoc 当转化适用于以下XML文件时(无杂志):

<Library>
    <Item type="XXXXX" title="Rum"/>
    <Item type="book" title="Foo" author="Bar"/>
    <Item type="book" title="Fib" author="Fub"/>
    <Item type="YYYYY" title="Baz"/>
</Library>

again 正确结果(杂志的电传、书本的正常结果):

  Sorry: No Magazines
Type: book, title: Foo
Type: book, title: Fib

Similarly, we get the wanted results when there are no books, or when both kind of items are missing.

Do note:

  1. <>范围更广>(无模式,无明确的有条件指示)。

  2. www.un.org/spanish/ecosoc 最低模板编号(不论可能不同类型的数目,对单一错误处理模板加以调整)。

  3. Only one <xsl:apply-templates> 特定类型的处理:——不需要特别添加<代码><xsl:apply-templates>用于错误处理。

  4. <>弹性、易读性、可维持性<>/strong>->>>>> 代码 可在各自的单独档案中居住。

为什么不使用与“无杂志”和“无书籍”相匹配的模板:

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

<xsl:template match="Library">
  <xsl:apply-templates select="Item" />
  <!-- Apply no[books|magazines] from here -->
  <xsl:apply-templates select="." mode="noresults" />
</xsl:template>

<xsl:template match="Item[@type= book ]">
  <!-- do something with books -->
</xsl:template>

<xsl:template match="Item[@type= magazine ]">
  <!-- do something with magazines -->
</xsl:template>

<xsl:template match="Library[not(Item[@type= book ])]" mode="noresults" >
  Sorry, No Books!
</xsl:template>

<xsl:template match="Library[not(Item[@type= magazine ])]" mode="noresults" >
  Sorry, No Magazines!
</xsl:template>

</xsl:stylesheet>

这确实是一个原始想法。 这在迈克尔的解决方案上只是一个 t子。 看来文件功能对XSLT1.0来说是一个次要问题,因此我试图避免。

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:msxsl="urn:schemas-microsoft-com:xslt">
 <xsl:output method="text"/>

 <xsl:variable name="vErrorObjects">
  <Books/><Magazines/>
 </xsl:variable>

 <xsl:template match="/Library">
  <xsl:apply-templates select="*[@type= magazine ],$vErrorObjects/Magazines"/>   
  <xsl:apply-templates select="*[@type= book     ],$vErrorObjects/Books"    />
 </xsl:template>

 <xsl:template match="Item">
  <xsl:value-of select="concat( &#xA;Type:  , @type,  , title:  , @title)"/>
 </xsl:template>

 <xsl:template match="Magazines|Books">
  <xsl:if test="last() = 1">
    Sorry: No <xsl:value-of select="local-name()"/>
  </xsl:if>
 </xsl:template>

</xsl:stylesheet>




相关问题
When test hanging in an infinite loop

I m tokenising a string with XSLT 1.0 and trying to prevent empty strings from being recognised as tokens. Here s the entire function, based on XSLT Cookbook: <xsl:template name="tokenize"> ...

quick xslt for-each question

Let s say I have an XML document that has this: <keywords> <keyword>test</keyword> <keyword>test2</keyword> <keyword>test3</keyword> <keyword>test4</...

XSLT Transform XML with Namespaces

I m trying to transform some XML into HTML using XSLT. Problem: I can t get it to work. Can someone tell me what I m doing wrong? XML: <ArrayOfBrokerage xmlns:i="http://www.w3.org/2001/...

XSLT output to HTML

In my XSLT file, I have the following: <input type="button" value= <xsl:value-of select="name">> It s an error as it violates XML rule. What I actually want is having a value from an ...

Mangling IDs and References to IDs in XML

I m trying to compose xml elements into each other, and the problem I am having is when there s the same IDs. Basically what I need to do is mangle all the IDs in an xml file, as well as the ...

Sharepoint 2007 Data view Webpart custom parameters

I m sort of new to the custom parameters that can be setup on a DataView Webpart. There are 6 options: - None - Control - Cookie - Form - QueryString - Server Variable I think that None, Cookie and ...

热门标签