0

我正在尝试过滤记录集,并且我已经让它与以下 XSLT 一起使用,但它看起来一点也不好看:

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

    <xsl:template match="/">
        <xsl:element name="Response">
            <xsl:element name="rcode">
                <xsl:text>0</xsl:text>
            </xsl:element>
            <xsl:element name="rmesage">
                <xsl:text>0</xsl:text>
            </xsl:element>
            <xsl:element name="payload">

                <xsl:for-each select="Response/payload/globalBuy[season='A09']">

                    <xsl:element name="season"><xsl:value-of select="season"/></xsl:element>
                    <xsl:element name="productId"><xsl:value-of select="productId"/></xsl:element>
                    <xsl:element name="globalBuyFlag"><xsl:value-of select="globalBuyFlag"/></xsl:element>

                </xsl:for-each>

            </xsl:element>
        </xsl:element>

    </xsl:template>

</xsl:stylesheet>

此外,当命名空间在根目录中弹出时,我看到了问题。下面的示例 XML:

<?xml version="1.0" encoding="UTF8"?>
<Response xmlns="http://www.castiron.com/response">
    <payload>
        <globalBuy>
            <season>CD12</season>
            <productId>123456</productId>
            <globalBuyFlag>XXL</globalBuyFlag>
        </globalBuy>
    </payload>
</Response>
4

2 回答 2

2

您可以通过删除xsl:element的所有用途来简化您的代码。除非您希望动态生成元素名称,否则将元素写为普通 XML 非常简单。所以不用写这个......

<xsl:element name="rcode">
    <xsl:text>0</xsl:text>
</xsl:element> 

就写这个...

<rcode>0</rcode>

至于过滤,如果您只想复制 XML,但只包含与过滤器匹配的某些项目,那么您可以覆盖身份模板,并让模板与您不想包含的项目匹配然后简单地忽略他们。

试试这个简化的 XSLT

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

   <xsl:template match="/Response">
      <xsl:copy>
         <xsl:apply-templates select="@*" />
         <rcode>0</rcode>
         <rmesage>0</rmesage>
         <xsl:apply-templates select="node()"/>
      </xsl:copy>
   </xsl:template>

   <xsl:template match="globalBuy[not(season='A09')]" />

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

应用于以下 XML 时

<Response>
   <payload>
      <globalBuy>
         <season>CD12</season>
         <productId>123456</productId>
         <globalBuyFlag>XXL</globalBuyFlag>
      </globalBuy>
      <globalBuy>
         <season>A09</season>
         <productId>123456b</productId>
         <globalBuyFlag>XXLb</globalBuyFlag>
      </globalBuy>
   </payload>
</Response>

然后输出如下

<Response>
   <rcode>0</rcode>
   <rmesage>0</rmesage>
   <payload>
      <globalBuy>
         <season>A09</season>
         <productId>123456b</productId>
      <globalBuyFlag>XXLb</globalBuyFlag>
   </globalBuy>
   </payload>
</Response>

请注意,我在此示例中删除了所有名称空间以使事情更简单。

编辑:如果您确实想处理默认名称空间,在 XSLT 1.0 中,您将明确引用您匹配的每个元素的名称空间。你会做这样的事情:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:r="http://www.castiron.com/response" exclude-result-prefixes="r">
   <xsl:output method="xml" indent="yes"/>

   <xsl:template match="/r:Response">
      <xsl:copy>
         <rcode xmlns="http://www.castiron.com/response">0</rcode>
         <rmesage xmlns="http://www.castiron.com/response">0</rmesage>
         <xsl:apply-templates select="@*|node()"/>
      </xsl:copy>
   </xsl:template>

   <xsl:template match="r:globalBuy[not(r:season='A09')]" />

   <xsl:template match="@*|node()">
      <xsl:copy>
         <xsl:apply-templates select="@*|node()"/>
      </xsl:copy>
   </xsl:template>   
</xsl:stylesheet>
于 2012-04-30T16:31:57.937 回答
2

美在旁观者的眼中; 我不确定您的代码的哪个方面不好看。但我会从这样重写它开始:

<xsl:template match="/">
    <Response>
        <rcode>0</rcode>
        <rmesage>0</rmesage>
        <payload>
            <xsl:copy-of select="Response/payload/globalBuy[season='A09']/
                                    (season, productId, globalBuyFlag)">
        </payload>
    </Response>

</xsl:template>

xsl:copy-of 表达式使用 XPath 2.0;如果你想要一个 XSLT 1.0 解决方案,你必须把 xsl:for-each 放回去。

至于命名空间,只需在谷歌上搜索“XSLT 默认命名空间”,您就会发现一百万个解释您的错误的帖子。

于 2012-04-30T16:36:28.443 回答