在新父节点中换行节点?

时间:2016-04-29 15:18:26

标签: xml csv xslt xpath transformation

我正在使用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>个节点。我在这里错过了什么?欢迎任何帮助。

1 个答案:

答案 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语句的变量的新内容。

编辑:在回复评论时,请注意,在模板匹配开始时没有必要使用双斜杠//