我正在使用XSLT样式表将CSV转换为XML,但我还需要在CSV转换后使用一些模板转换XML。下面是应该将任何<UPC>031878025147</UPC>
节点包装为:
<UPCs>
<UPC>031878025147</UPC>
<UPCs>
这是样式表的片段,它应该用<UPC>
包裹<UPCs>
个节点:
<?xml version='1.0' encoding='UTF-8'?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fn="fn"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
version="2.0" exclude-result-prefixes="xs fn">
<xsl:output method="xml" indent="yes" encoding="UTF-8" />
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="//UPC[preceding-sibling::ExternalId]">
<xsl:variable select="." name="curElem" />
<xsl:for-each select=".">
<UPCs>
<xsl:copy-of select="$curElem" />
</UPCs>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
这是一个解析的XML片段:
<Feed name="example" incremental="false" extractDate="2016-04-28T13:42:09-05:00" xmlns="http://www.bazaarvoice.com/xs/PRR/ProductFeed/14.5">
<Brands>
<Brand removed="false">
<ExternalId>brands</ExternalId>
<Name>Brands</Name>
<!--BrandPageUrl>http://www.kolcraft.com/brands.html</BrandPageUrl-->
</Brand>
<!-- ... -->
</Brands>
<Categories>
<Category removed="false">
<ExternalId>baby-products</ExternalId>
<Name>Baby Products</Name>
<CategoryPageUrl>http://www.kolcraft.com/baby-products.html</CategoryPageUrl>
</Category>
</Categories>
<Products>
<Product>
<ExternalId>ED003-QCX</ExternalId>
<UPC>031878025147</UPC>
<Name>Sealy Naturals-Cotton Crib Mattress Pad</Name>
<Description>Give baby plush comfort from natural cotton fibers with the innovative Sealy Naturals-Cotton Crib Mattress Pad.</Description>
<ProductPageUrl>http://www.kolcraft.com/sealy-naturals-cotton-crib-mattress-pad.html</ProductPageUrl>
<ImageUrl>http://www.kolcraft.com/media/catalog/product/e/d/ed003-qcx-1_1_4.jpg</ImageUrl>
<CategoryExternalId>crib-bedding</CategoryExternalId>
</Product>
<!-- ... -->
</Products>
</Feed>
但是,这似乎没有捕获父<UPC>
节点之外的任何<UPCs>
个节点。我在这里错过了什么?欢迎任何帮助。
答案 0 :(得分:1)
这是因为您在XML中有一个默认的名称空间声明
<Feed ... xmlns="http://www.bazaarvoice.com/xs/PRR/ProductFeed/14.5">
这意味着Feed
元素和所有后代元素都在该命名空间中。但是,您的XSLT没有进入此命名空间,因此希望匹配没有命名空间的元素UPC
,这不是一回事。
在使用XSLT 2.0时,您实际上可以使用xpath-default-namespace
为xpath表达式指定默认名称空间,例如模板匹配。您还需要为XSLT定义默认命名空间,以确保新UPCs
在同一命名空间中输出。
试试这个XSLT
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fn="fn"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xpath-default-namespace="http://www.bazaarvoice.com/xs/PRR/ProductFeed/14.5"
xmlns="http://www.bazaarvoice.com/xs/PRR/ProductFeed/14.5"
version="2.0" exclude-result-prefixes="xs fn">
<xsl:output method="xml" indent="yes" encoding="UTF-8" />
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="UPC[preceding-sibling::ExternalId]">
<UPCs>
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</UPCs>
</xsl:template>
</xsl:stylesheet>
注意我也简化了模板,因为我无法看到for-each语句的变量的新内容。
编辑:在回复评论时,请注意,在模板匹配开始时没有必要使用双斜杠//
。