我正在尝试过滤一个记录集,我已经让它可以使用以下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>
答案 0 :(得分:2)
您可以通过删除 xsl:element 的所有用途来简化您的代码。除非您希望动态生成元素名称,否则将元素写为普通XML非常简单。所以不要写这个....
<xsl:element name="rcode">
<xsl:text>0</xsl:text>
</xsl:element>
写这个......
<rcode>0</rcode>
对于过滤,如果您要做的只是复制XML,但只包含与过滤器匹配的某些项目,那么您可以覆盖标识模板,并使模板匹配您不<的项目/ strong>想要包含,只是忽略它们。
试试这个简化的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>
答案 1 :(得分: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默认命名空间”,你就会找到一百万个帖子来解释你的错误。