如果在数组中匹配则运行XSL转换,如果没有则如何丢弃?

时间:2014-04-15 18:03:57

标签: xml bash xslt

我想根据文章编号将某些文章导入数据库。允许的文章编号位于“allowedArticles”变量中。如果允许导入文章,则应导入该文章的所有内容。 (文章列表会更大,下面的例子只是一个例子。)

与我列表中的某篇文章不匹配的文章应该以某种方式丢弃。

此XSLT将在多个文件上运行,因为导出是使用每个文件中的一个项目进行的,尽管这可能是一个大文件中的所有项目。用一个大文件做我想要的更容易吗?

这是否可以使用XSLT,如果是这样,最好的解决方案是什么?我是否应该编写一个可以支持此操作的bash脚本?

您还需要更多信息吗?

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"
  xpath-default-namespace="http://xmlns.escenic.com/2009/import">
  <xsl:output omit-xml-declaration="no" indent="yes"/>

  <!-- Array of articles to include in the import, optimize by loading from external file -->
  <xsl:variable name="allowedArticles" as="element()*">
    <Item>86369</Item><Item>81563</Item><Item>68333</Item><Item>67772</Item>
  </xsl:variable>


  <!-- If the article ID is NOT in allowedArticles do nothing with them -->
  <xsl:template match="/escenic/content">
    <xsl:variable name="exportedDbId" select="@exported-dbid" />
    <xsl:for-each select="$allowedArticles">
      <xsl:choose>
        <xsl:when test="$exportedDbId=.">
          <!-- Identity template : copy all text nodes, elements and attributes -->
          <!-- It does not work to copy all nodes from here, as it's the wrong context or something like that. -->
        </xsl:when>
        <xsl:otherwise />
      </xsl:choose>
    </xsl:for-each>
  </xsl:template>
</xsl:stylesheet>

1 个答案:

答案 0 :(得分:2)

与我列表中某篇文章不匹配的文章应该以某种方式丢弃。

所以如果我坚持并且你想要做的就是删除那些不允许的元素&#34;你可以这样做:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"
    xpath-default-namespace="http://xmlns.escenic.com/2009/import">

<xsl:output omit-xml-declaration="no" indent="yes"/>

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

<xsl:variable name="allowedArticles" as="element()*">
    <Item>86369</Item><Item>81563</Item><Item>68333</Item><Item>67772</Item>
</xsl:variable>

<!-- empty template to discard content elements that are not in allowedArticles -->
<xsl:template match="content[not(@exported-dbid=$allowedArticles/Item)]"/>

</xsl:stylesheet>

身份模板将复制所有内容,空模板将与您不允许的文章匹配并丢弃它们。

修改

正如@tomalak所说,序列将是一种更优雅的方式来处理您的允许ID:

<xsl:variable name="AllowedItems" select="(86369, 81563, 68333, 67772)"/>

要回答评论中的问题,这等于:

<xsl:variable name="AllowedItems">
    <xsl:sequence select="(86369, 81563, 68333, 67772)"/>
</xsl:variable>

如果你想从外部文件中引用AllowedItems,让我们假设你有一个名为AllowedItems.xml的文件,如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<AllowedItems>
    <Item>86369</Item>
    <Item>81563</Item>
    <Item>68333</Item>
    <Item>67772</Item>
</AllowedItems>

然后你定义你的变量:

<xsl:variable name="AllowedItems"
     select="document('AllowedItems.xml')/AllowedItems/Item"/>

这里的document()函数要求AllowedItems.xml与xslt位于同一目录中,你也可以在这里使用相对路径或完整的Uri,你可以阅读文档here


此XSLT将在多个文件上运行,因为导出是在每个文件中使用一个项目进行的,尽管这可能是一个大文件中的所有项目。用一个大文件做我想要的更容易吗?

我认为这是偏好和/或性能问题,取决于您的输入文件和您的具体方案。我通常更喜欢对很多较小的转换进行一次转换,但是文件越大,你可能会有更多的转换。