XSLT转换选择具有特定属性值的元素



嗨,我有以下xml

<?xml version="1.0" encoding="UTF-8"?>
<catalog catalog-id="Primary">
<product product-id="clothes">
    <items>
        <item item-name="TShirt">Brown</item>
        <item item-name="Pants">Green</item>
        <item item-name="Shirt">White</item>
    </items>
</product>
<product product-id="toys">
    <items>
        <item item-name="Ball">Cyan</item>
        <item item-name="Bat">Green</item>
        <item item-name="Racket">Blue</item>
    </items>
</product>
</catalog>

标准仅是复制" item-name"属性值是T恤,球或蝙蝠。因此,由此产生的XML应该看起来像

<?xml version="1.0" encoding="UTF-8"?>
<catalog catalog-id="Primary">
<product product-id="clothes">
    <items>
        <item item-name="TShirt">Brown</item>
    </items>
</product>
<product product-id="toys">
    <items>
        <item item-name="Ball">Cyan</item>
        <item item-name="Bat">Green</item>
    </items>
</product>
</catalog>

我正在使用以下XSLT

<xsl:stylesheet version="1.0"       xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xsl:output method="xml" indent="yes"/>
    <xsl:strip-space elements="*"/>
 <xs:WhiteList>
  <item-name>TShirt</item-name>
  <item-name>Ball</item-name>
  <item-name>Green</item-name>
 </xs:WhiteList>
 <xsl:variable name="whiteList" select="document('')/*/xs:WhiteList" />
 <xsl:template match="node()|@*">
     <xsl:copy>
       <xsl:apply-templates select="node()|@*"/>
     </xsl:copy>
 </xsl:template>
 <xsl:template match="*[(descendant-or-self::*[name()=$whiteList/item-name])"/>
</xsl:stylesheet>

但这不起作用。你能帮忙吗?

谢谢内森

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output method="xml" indent="yes"/>
    <xsl:strip-space elements="*"/>
    <xsl:template match="node() | @*">
        <xsl:copy>
            <xsl:apply-templates select="node() | @*"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template
        match="item[not(@item-name = 'TShirt' or @item-name = 'Ball' or @item-name = 'Bat')]"/>
</xsl:stylesheet>

这也会生成输出。这是基于XSLT 1.0。

在XSLT 1.0中,您不能在xsl:template匹配模式中使用变量参考。您可能应该匹配item,然后在模板内进行测试。

我还建议您使用唯一的名称空间为您的白名单而不是使用xmlns:xs="http://www.w3.org/2001/XMLSchema"

我注意到的另一件事是,您的白名单中有Green,而不是Bat

这是一个更新这三件事的示例...

XML输入

<catalog catalog-id="Primary">
    <product product-id="clothes">
        <items>
            <item item-name="TShirt">Brown</item>
            <item item-name="Pants">Green</item>
            <item item-name="Shirt">White</item>
        </items>
    </product>
    <product product-id="toys">
        <items>
            <item item-name="Ball">Cyan</item>
            <item item-name="Bat">Green</item>
            <item item-name="Racket">Blue</item>
        </items>
    </product>
</catalog>

XSLT 1.0

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
  xmlns:local="local">
  <xsl:output method="xml" indent="yes"/>
  <xsl:strip-space elements="*"/>
  <local:WhiteList>
    <item-name>TShirt</item-name>
    <item-name>Ball</item-name>
    <item-name>Bat</item-name>
  </local:WhiteList>
  <xsl:variable name="whiteList" 
    select="document('')/*/local:WhiteList/item-name"/>
  <xsl:template match="node()|@*">
    <xsl:copy>
      <xsl:apply-templates select="node()|@*"/>
    </xsl:copy>
  </xsl:template>
  <xsl:template match="item">
    <xsl:if test="@item-name=$whiteList">
      <xsl:copy-of select="."/>
    </xsl:if>    
  </xsl:template>
</xsl:stylesheet>

XML输出

<catalog catalog-id="Primary">
   <product product-id="clothes">
      <items>
         <item item-name="TShirt">Brown</item>
      </items>
   </product>
   <product product-id="toys">
      <items>
         <item item-name="Ball">Cyan</item>
         <item item-name="Bat">Green</item>
      </items>
   </product>
</catalog>

没有什么可以阻止您在模板匹配表达式中使用document()函数。

以下产生所述输出:

<xsl:stylesheet version="1.0"       
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
                xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xsl:output method="xml" indent="yes"/>
  <xsl:strip-space elements="*"/>
  <xs:WhiteList>
    <item-name>TShirt</item-name>
    <item-name>Ball</item-name>
    <item-name>Bat</item-name>
  </xs:WhiteList>
  <xsl:template match="node()|@*">
    <xsl:copy>
      <xsl:apply-templates select="node()|@*"/>
    </xsl:copy>
  </xsl:template>
  <xsl:template match="item[not(@item-name = document('')/*/xs:WhiteList/item-name)]"/>
</xsl:stylesheet>

作为旁注,我建议不要滥用名称空间。您的xs:WhiteListhttp://www.w3.org/2001/XMLSchema名称空间无关。如果需要的话,可以使用像xmlns:ut="my-utility-nodes"这样的化妆名称空间,它不太可能与实际使用中的任何东西发生冲突。

最新更新