XSLT问题... CSV问题。?

时间:2013-10-20 02:37:18

标签: xml xslt xslt-1.0

如果 parent_item 列中的值在CSV文件中出现的次数超过1次,我需要对CSV文件的每一行进行评估。我需要将一个布尔输出到一个新列 - 让它标记为 parent_count 。如果parent_item列中的值在CSV文件中出现2次或更多次,则输出TRUE到parent_count,否则输出FALSE到parent_count字段。如果可以使用XSLT中的代码完成此操作,有人可以帮助我。

文件将从XML转换为CSV。

请帮助我,因为我是XSLT的新手。

修改

<AdditionalAttributes groupLabel="Custom Attributes">
    <AdditionalAttribute dataType="Decimal" value="" name="Standard Cost" dimension="$"/>
    <AdditionalAttribute dataType="Decimal" value="" name="Target Cost" dimension="$"/>
    <AdditionalAttribute dataType="Decimal" value="" name="Target Price" dimension="$"/>
    <AdditionalAttribute description="quoted" dataType="Decimal" value="" name="Active Cost #1" dimension="$"/>
    <AdditionalAttribute description="quoted" dataType="Decimal" value="" name="Active Cost #2" dimension="$"/>
    <AdditionalAttribute dataType="String" value="" name="Active Cost Line #1"/>
    <AdditionalAttribute dataType="String" value="" name="Active Cost Line #2"/>
    <AdditionalAttribute dataType="String" value="" name="Description"/>
    <AdditionalAttribute dataType="String" value="Off-the-Shelf (OTS)" name="Procurement Type"/>
    <AdditionalAttribute dataType="String" value="OTHER" name="General Posting Group"/>
    <AdditionalAttribute dataType="String" value="OTHER" name="Inventory Posting Group"/>
    <AdditionalAttribute dataType="String" value="PARTS" name="Item Category Group"/>
</AdditionalAttributes>

编辑要求

我有一个 parent_item 列,其中的值是这样的

  • parent_item parent_count

    1. 第1行:441-0230-001 true

    2. 第2行:441-0230-001 true

    3. 第3行:441-0230-001 true

    4. 第4行:441-0230-001是

    5. 第5行:SP-SSD-80GB错误

现在第4行中的值对4条记录重复4次,因此parent_count中的值为true。 父项中的第5行值只出现一次。所以父计数为false。

这是我的确切要求。您可以帮助我实现这一目标。我是XSL编码的新手。

新XML

<Item
   itemIdentifier="650-0107-001"
   itemUniqueIdentifier="IVI10144102348"
   globalLifeCyclePhaseCode="Production"
   globalProductTypeCode="6xx - PCBA&apos;s"
   revisionIdentifier="A"
   proprietaryProductFamily=""
   category="6xx - PCBA&apos;s"
   globalProductUnitOfMeasureCode="FA"
   revisionReleasedDate="2013-07-31T00:00:00-08:00"
   ownerName=""
   isTopLevel="Yes"
   description="Transceivers">

  <AdditionalAttributes groupLabel="Version Information">
    <AdditionalAttribute name="Version Notes" value="test" dataType="String"></AdditionalAttribute>
    <AdditionalAttribute name="Change Number" value="DEV-000130" dataType="String"></AdditionalAttribute>
    <AdditionalAttribute name="Version Shared" value="Yes" dataType="String"></AdditionalAttribute>
    <AdditionalAttribute name="Effective Version Shared" value="Yes" dataType="String"></AdditionalAttribute>
    <AdditionalAttribute name="Material Effectivity Date" value="2013-05-20T11:05:41-08:00" dataType="String"></AdditionalAttribute>
    <AdditionalAttribute name="Disposition Notes" value="In the Field =N/A- Does Not Apply; WIP =N/A-Does Not Apply; On Order =N/A-Does Not Apply; Finished Goods =N/A-Does Not Apply; In Stock =See Notes; In Stock Notes=Authorize existing stock until specified expiration 7/31/2013; Depot =N/A- Does Not Apply; CTO-Configure to Order =N/A-Does Not Apply" dataType="String"></AdditionalAttribute>
    <AdditionalAttribute name="Item Creation Date" value="2012-07-06T12:14:03-08:00" dataType="String"></AdditionalAttribute>
  </AdditionalAttributes>
</Item>

XSLT代码

这是我添加列

的代码
<map:attribute type="internal" ref="id" container="Item">
    <map:aren>itemIdentifier</map:aren>
    <map:generic delimiter="false" name="parent_item" width="50"/>
</map:attribute>

1 个答案:

答案 0 :(得分:2)

如果您的数据的源格式是XML格式,那么绝对可以使用XSLT完成。您可以迭代表示未来CSV文件中一行的标记,然后使用带有count的xpath表达式来进行所需的测试。

根据您的输入,我将假设我们有以下(为简洁而简化)输入文件:

<?xml version="1.0" encoding="ISO-8859-1"?>
<Items>
  <Item
      itemIdentifier="650-0107-001"
      itemUniqueIdentifier="IVI99999999999"
      description="Transceivers">
    <AdditionalAttributes groupLabel="Custom Attributes">
      <AdditionalAttribute dataType="String" value="OTHER1" name="Inventory Posting Group"/>
      <AdditionalAttribute dataType="String" value="PARTS1" name="Item Category Group"/>
    </AdditionalAttributes>
  </Item>
  <Item
      itemIdentifier="650-0107-001"
      itemUniqueIdentifier="IVI10144102348"
      description="Receivers">
    <AdditionalAttributes groupLabel="Custom Attributes">
      <AdditionalAttribute dataType="String" value="OTHER2" name="Inventory Posting Group"/>
      <AdditionalAttribute dataType="String" value="PARTS2" name="Item Category Group"/>
    </AdditionalAttributes>
  </Item>
  <Item
      itemIdentifier="SP-SSD-80GB"
      itemUniqueIdentifier="IVI10144102348"
      description="Transmitters">
    <AdditionalAttributes groupLabel="Custom Attributes">
      <AdditionalAttribute dataType="String" value="OTHER3" name="Inventory Posting Group"/>
      <AdditionalAttribute dataType="String" value="PARTS3" name="Item Category Group"/>
    </AdditionalAttributes>
  </Item>
</Items>

此外,我们还有一些小的映射文件,用于定义parent_item

<?xml version="1.0" encoding="ISO-8859-1" ?>
<maps xmlns:map="http://my.namespace">
  <map:attribute 
      type="internal" ref="id" container="Item">
    <map:aren>itemIdentifier</map:aren>
    <map:generic delimiter="false" name="parent_item" width="50"/>
  </map:attribute>
</maps>

使用简单版本的反射local-name())(参见Get tag name/attribute name in XML using XSLT)以下XSLT表

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet 
    version="1.0"
    xmlns:map="http://my.namespace"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:param name="map_name"/>
  <xsl:variable name="map" select="document($map_name)"/>

  <xsl:output method="text"/>

  <xsl:template match="/Items">

    <xsl:for-each select="Item">

      <xsl:for-each select="@*">

        <!-- output the attribute value -->
        <xsl:value-of select="."/><xsl:text>;</xsl:text>
        <!-- get the name of parent_item attribute from the map -->
        <xsl:variable name="parent_item" select="$map/maps/map:attribute/map:aren/text()"/>

        <!-- if the current attribute is a parent_item execute the uniqueness check -->
        <xsl:if test="$map/maps/map:attribute/map:aren = local-name(.)">

          <!-- introduce local variable for easy test below-->
          <xsl:variable name="current_parent_value" select="../@*[local-name(.) = $parent_item]"/>
          <!-- compute the boolean column depending on the count of current_parent_item -->
          <xsl:variable name="parent_count">

            <xsl:choose>
              <!-- note that we have to compare > 1 (and not > 0) since an entry will ALWAYS find itself -->
              <xsl:when test="count(/Items/Item[ @*[local-name(.) = $parent_item] = $current_parent_value]) > 1">
                <xsl:text>TRUE</xsl:text>
              </xsl:when>
              <xsl:otherwise>
                <xsl:text>FALSE</xsl:text>            
              </xsl:otherwise>
            </xsl:choose>
          </xsl:variable>
          <!-- output the result of the uniqueness check -->
          <xsl:value-of select="$parent_count"/><xsl:text>;</xsl:text>

        </xsl:if>

      </xsl:for-each>

      <xsl:for-each select="AdditionalAttributes/AdditionalAttribute">
        <!-- output the values of the remaining attributes -->
        <xsl:value-of select="@value"/><xsl:text>;</xsl:text>
      </xsl:for-each>

      <xsl:text>&#10;</xsl:text>

    </xsl:for-each>

  </xsl:template>
</xsl:stylesheet>

将生成CSV结果文件

650-0107-001;TRUE;IVI99999999999;Transceivers;OTHER1;PARTS1;
650-0107-001;TRUE;IVI10144102348;Receivers;OTHER2;PARTS2;
SP-SSD-80GB;FALSE;IVI10144102348;Transmitters;OTHER3;PARTS3;

如果我们使用不同的地图文件

<?xml version="1.0" encoding="ISO-8859-1" ?>
<maps xmlns:map="http://my.namespace">
  <map:attribute 
      type="internal" ref="id" container="Item">
    <map:aren>itemUniqueIdentifier</map:aren>
    <map:generic delimiter="false" name="parent_item" width="50"/>
  </map:attribute>
</maps>

我们会得到这个结果:

650-0107-001;IVI99999999999;FALSE;Transceivers;OTHER1;PARTS1;
650-0107-001;IVI10144102348;TRUE;Receivers;OTHER2;PARTS2;
SP-SSD-80GB;IVI10144102348;TRUE;Transmitters;OTHER3;PARTS3;

注意:

  • 地图文件的名称作为参数map_name传递。您必须了解它如何适用于您的处理器。如果是xlstproc,则必须使用   xsltproc --stringparam map_name“map.xml”convert.xslt input.xml&gt; output.csv
  • 代码仍假设parent_item所在的标记。原则上你可以通过遍历文档来匹配标签来使这更加通用,但我并不认为你需要这个。
  • 从地图文件中提取parent_item的名称相当简单。如果适用,您可能需要添加其他过滤。
  • 当然,您必须根据需要微调输出。迭代输出属性的通用方法只是一个例子。
  • 这对我来说是一项有趣的任务,因为这是我第一次在XLS中使用 reflection 。 : - )