XSLT 1如果不在列表中,则排除父元素

时间:2015-02-23 10:02:31

标签: xslt

我想执行xslt转换,我按类型拆分产品。举个例子:

源XML:

 <Products>
    <Product>
       <Name>Cheese</Name>
       <Value>30</Value>
    </Product>
    <Product>
       <Name>Bread</Name>
       <Value>10</Value>
    </Product>
    <Product>
       <Name>Bacon</Name>
       <Value>100</Value>
    </Product>
 </Products>

必需的输出XML:

<Products>
    <AnimalProducts>
    <Product>
        <Name>Cheese</Name>
        <Value>30</Value>
    </Product>
    <Product>
        <Name>Bacon</Name>
        <Value>100</Value>
    </Product>
    </AnimalProducts>
    <VeganProducts>
    <Product>
        <Name>Bread</Name>
        <Value>10</Value>
    </Product>
    </VeganProducts>
</Products>

如果没有动物产品或没有素食产品,则不应包括父母元素。我有一半的工作:

<xsl:variable name="veganProducts" select="'Bread:Lettuce'" />

<xsl:if test="Products/Product[count(*) &gt; 0]">
            <AnimalProducts>
                <xsl:for-each select="Products/Product">
                    <xsl:if test="not(contains(concat(':', $veganProducts, ':'), concat(':', Name, ':')))">     
                        <Product>
                            <Name>
                                <xsl:value-of select="Name" />
                            </Name>
                            <Value>
                                <xsl:value-of select="Value" />
                            </Value>
                        </Product>
                    </xsl:if>
                </xsl:for-each>
            </AnimalProducts>

            <VeganProducts>
                <xsl:for-each select="Products/Product">
                    <xsl:if test="contains(concat(':', $veganProducts, ':'), concat(':', Name, ':'))">     
                        <Product>
                            <Name>
                                <xsl:value-of select="Name" />
                            </Name>
                            <Value>
                                <xsl:value-of select="Value" />
                            </Value>
                        </Product>
                    </xsl:if>
                </xsl:for-each>
            </VeganProducts>
</xsl:if>

问题是如果在某些情况下没有纯素或动物产品,我会得到空的父元素。我不确定如何测试这个。

2 个答案:

答案 0 :(得分:1)

现在是利用变量的好时机:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>

  <xsl:variable name="veganProductNames" select="'Bread:Lettuce'" />
  <xsl:variable name="veganProductNamesPadded" 
                select="concat(':', $veganProductNames, ':')" />

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

  <xsl:template match="/*">
    <xsl:copy>
      <xsl:variable name="animalProducts"
                    select="Product[not(contains($veganProductNamesPadded,
                                                 concat(':', Name, ':')))]" />
      <xsl:variable name="veganProducts"
                    select="Product[contains($veganProductNamesPadded,
                                             concat(':', Name, ':'))]" />

      <xsl:if test="$animalProducts">
        <AnimalProducts>
          <xsl:apply-templates select="$animalProducts" />
        </AnimalProducts>
      </xsl:if>
      <xsl:if test="$veganProducts">
        <VeganProducts>
          <xsl:apply-templates select="$veganProducts" />
        </VeganProducts>
      </xsl:if>
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

在样本输入上运行时,结果为:

<Products>
  <AnimalProducts>
    <Product>
       <Name>Cheese</Name>
       <Value>30</Value>
    </Product>
    <Product>
       <Name>Bacon</Name>
       <Value>100</Value>
    </Product>
  </AnimalProducts>
  <VeganProducts>
    <Product>
       <Name>Bread</Name>
       <Value>10</Value>
    </Product>
  </VeganProducts>
</Products>

答案 1 :(得分:0)

我更愿意用XML方式解决这个问题:

XSLT 1.0

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:my="http://www.example.com/my"
exclude-result-prefixes="my">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

<my:vegan-items>
    <item>Bread</item>
    <item>Lettuce</item>
</my:vegan-items>

<xsl:variable name="vegan-items" select="document('')/xsl:stylesheet/my:vegan-items/item" />

<xsl:template match="/Products">
    <xsl:variable name="vegan-products" select="Product[Name=$vegan-items]" />
    <xsl:variable name="animal-products" select="Product[not(Name=$vegan-items)]" />
    <xsl:copy>
        <xsl:if test="$animal-products">
            <AnimalProducts>
                <xsl:copy-of select="$animal-products"/>
            </AnimalProducts>
        </xsl:if>
        <xsl:if test="$vegan-products">
            <VeganProducts>
                <xsl:copy-of select="$vegan-products"/>
            </VeganProducts>
        </xsl:if>
    </xsl:copy>                             
 </xsl:template>

</xsl:stylesheet>

我们假设任何不是“素食主义者”的东西都是“动物”(因为没有提供“动物”物品清单)。

保留列出每个类别中项目的外部XML文档可能会更好。