【问题标题】:XSLT issue...CSV issue.?XSLT 问题...CSV 问题。?
【发布时间】:2013-10-20 02:37:18
【问题描述】:

如果 parent_item 列中的值在 CSV 文件中出现超过 1 次,我需要对 CSV 文件的每一行进行评估。我需要将布尔值输出到新列 - 让我们标记它parent_count。如果 parent_item 列中的值在 CSV 文件中出现 2 次或更多次,则向 parent_count 输出 TRUE,否则向 parent_count 字段输出 FALSE。如果可以使用 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 正确

    2. 第 2 行:441-0230-001 正确

    3. 第 3 行:441-0230-001 正确

    4. 第 4 行:441-0230-001 正确

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

现在第 1 行中的值对 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>

【问题讨论】:

    标签: xml xslt xslt-1.0


    【解决方案1】:

    如果您的数据源格式是 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>
    

    使用 reflection (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 > output.csv
    • 代码仍然假设parent_item 所在的标签。原则上,您可以通过遍历文档以匹配标签来使其更加通用,但我不认为您需要这个。
    • 从地图文件中提取parent_item 的名称非常简单。如果适用,您可能需要添加额外的过滤。
    • 当然,您必须根据需要微调输出。迭代输出属性的通用方法只是一个示例。
    • 这对我来说是一项有趣的任务,因为这是我第一次在 XLS 中使用 reflection。 :-)

    【讨论】:

    • 感谢 Marcus 的回答。我对这个 XSLT 有新的了解,请您帮帮我..我提供了我的意见...您能建议如何执行此操作..?
    • 谢谢马库斯...抱歉我的回复晚了..我已经更新了我的确切要求..你能帮我这样做..我会很感激你...谢谢..跨度>
    • 我认为您应该相应地更新您的输入文件。由于 XSLT 很大程度上取决于 XML 的确切格式,因此在我调整我的解决方案之前了解它是必不可少的。坦率地说,我有点惊讶,因为我在 XML 文件中根本找不到您为 parent_item 添加的值。
    • 感谢您的快速回复..我已尝试更新 XML inmuy 问题,其中 parent_item 在那里..这是您想要的 XML。?还有什么其他的吗?
    • 问题是我们如何将数据输入到 XLST 处理器,因为它必须知道您的业务输入数据 &lt;Item&gt; 和您的配置数据 &lt;map&gt;同时。有两种简单的方法可以做到这一点:a) 准备一个包含两条信息的输入 XML 文件,或者 b) 在驱动输入文件中只有业务数据,然后从 XSLT 表中的另一个文件中读取配置数据。跨度>
    猜你喜欢
    • 2010-09-29
    • 1970-01-01
    • 1970-01-01
    • 2018-03-31
    • 2010-11-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多