XSLT 1.0 多通道

XSLT 1.0 multi-passing

我有以下输入 xml:

<bookstores>
  <store>
    <name>Store 1</name>
    <books>
      <book>
        <title>Book 1</title>
        <author>Author 1</author>
        <year>2000</year>
        <price/>
      </book>
      <book>
        <title>Book 2</title>
        <author></author>
        <year>2001</year>
        <price/>
      </book>
    </books>
  </store>
  <store>
    <name>Store 3</name>
    <books>
      <book>
        <title>Book 1</title>
        <year>2012</year>
        <price/>
      </book>
    </books>
  </store>
</bookstores>

我需要获取所有拥有已识别作者的书籍的商店,因此结果应该是:

<bookstores>
  <store>
    <name>Store 1</name>
    <books>
      <book>
        <title>Book 1</title>
        <author>Author 1</author>
        <year>2000</year>
        <price/>
      </book>
    </books>
  </store>
</bookstores>

我尝试使用 exslt:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:exslt="http://exslt.org/common">
  <xsl:output method="xml" indent="yes" encoding="utf-8" />
  <xsl:strip-space elements="*" />

  <xsl:template match="node()|@*">
    <xsl:copy>
      <xsl:apply-templates select="node()|@*" />
    </xsl:copy>
  </xsl:template>
  <xsl:template match="/">
    <xsl:variable name="firstPass">
      <xsl:call-template name="processing" />
    </xsl:variable>
    <xsl:apply-templates select="exslt:node-set($firstPass)" />
  </xsl:template>
  <xsl:template name="processing" match="bookstores/store/books/book[author[string()='']]" />
  <xsl:template match="bookstores/store/books/book[not(author)]" />
  <xsl:template match="bookstores/store[not(books/book)]" />

</xsl:stylesheet>
  1. 过滤作者为空的图书
  2. 过滤没有作者标签的图书
  3. 过滤掉没有作者书籍的书目

但不幸的是,我不知道如何以正确的方式使用它。如何将 exslt 与多个匹配模板一起使用?

我觉得你可以一次搞定

  <xsl:template match="store[not(books/book[author[normalize-space()]])]"/>

  <xsl:template match="book[not(author[normalize-space()])]"/>

这样完整的代码是

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

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

  <xsl:template match="store[not(books/book[author[normalize-space()]])]"/>

  <xsl:template match="book[not(author[normalize-space()])]"/>

</xsl:stylesheet>

并在 https://xsltfiddle.liberty-development.net/3NzcBtk 处给出想要的输出。

你的方法可以简化为

<xsl:template match="store/books/book[string(author)='']" />
<xsl:template match="store[not(books/book/author)]" />         

第一个在一个表达式中删除 book 没有 author 或空 author 的表达式。第二个删除 stores,它有 books 而没有 author 或者根本没有 books,因为没有 book 就不能成为 author.