将节点包装在新的父节点中?
Wrap node in new parent node?
我正在使用 XSLT 样式表将 CSV 转换为 XML,但我还需要在 CSV 转换后使用一些模板转换 XML。下面是样式表的一部分,应该将任何 <UPC>031878025147</UPC>
节点包装为:
<UPCs>
<UPC>031878025147</UPC>
<UPCs>
这是应该用 <UPCs>
包裹 <UPC>
节点的样式表片段:
<?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>
但是,这似乎没有捕获父 <UPCs>
节点之外的任何 <UPC>
节点。我在这里错过了什么?欢迎任何帮助。
这是因为您在 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 语句的新变量。
编辑:作为对评论的回应,请注意没有必要在模板匹配的开头使用双斜杠//
。
我正在使用 XSLT 样式表将 CSV 转换为 XML,但我还需要在 CSV 转换后使用一些模板转换 XML。下面是样式表的一部分,应该将任何 <UPC>031878025147</UPC>
节点包装为:
<UPCs>
<UPC>031878025147</UPC>
<UPCs>
这是应该用 <UPCs>
包裹 <UPC>
节点的样式表片段:
<?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>
但是,这似乎没有捕获父 <UPCs>
节点之外的任何 <UPC>
节点。我在这里错过了什么?欢迎任何帮助。
这是因为您在 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 语句的新变量。
编辑:作为对评论的回应,请注意没有必要在模板匹配的开头使用双斜杠//
。