1

我有一个包含对象(带有产品 SKU、名称等的产品)的大型 XML 文档 (13MB)。

对于应该从我的 XML 文档中删除的每个产品,我还有一个大的产品 SKU 列表(CSV,700 项)。

如果 XML 文档中的产品包含我列表中的 SKU,我想从 XML 文档中删除整个产品/对象。

以下是 XML 结构的示例:

<product>
  <Product_ID><![CDATA[1]]></Product_ID>
  <Product_Name><![CDATA[First product]]></Product_Name>
  <Product_CodeSKU><![CDATA[0000001]]></Product_CodeSKU>
</product>
<product>
  <Product_ID><![CDATA[2]]></Product_ID>
  <Product_Name><![CDATA[Second product]]></Product_Name>
  <Product_CodeSKU><![CDATA[0000002]]></Product_CodeSKU>
</product>
<product>
  <Product_ID><![CDATA[3]]></Product_ID>
  <Product_Name><![CDATA[Third product]]></Product_Name>
  <Product_CodeSKU><![CDATA[0000003]]></Product_CodeSKU>
</product>   

我的列表 (CSV) 包含诸如“0000001”之类的值。我想找到任何包含该值的产品,并将它们删除——​​同时保留其他产品不变。

4

3 回答 3

2

在 Vimscript 中,假设一个基于 UNIX 的系统:

fun! ClearSKUs()
  let command = "cat " . input("Enter path to CSV file: ")
  let data = system(command) | redraw!
  let values = split(substitute(data, "\n", "", ""), ",")
  for value in values
    if search(value) > 0
      silent ?<product?,/<\/product/d
    endif
  endfor
endfun

command! ClearSKUs call ClearSKUs()

要在编辑 XML 文档时运行,请使用:

:ClearSKUs

编辑:更新以替换match()search()@Ben 提到的,并使用单个普通命令。

编辑 2:更新以用给定的范围替换普通命令d(感谢@Ben!),并在收到输入后清除提示。

于 2013-10-09T04:07:25.943 回答
2

Well, here's an XSLT 2.0 solution:

<xsl:stylesheet...>

<xsl:variable name="removals" select="tokenize(unparsed-text('skus.csv'), '\n')"/> 

<xsl:template match="*">
  <xsl:copy><xsl:apply-templates/></xsl:copy>
</xsl:template>

<xsl:template match="product[Product_CodeSKU = $removals]"/>

</xsl:stylesheet>

Seems a lot simpler than @Ben's solution to me, and vastly faster.

Might need a little bit of adjustment because the format of the CSV file isn't clear to me.

于 2013-10-09T07:32:31.707 回答
2

好的,首先:如果我不止一次这样做,那么我会制作一个不错的 Perl 脚本,以完全自动化的方式为我完成。然后其他人也可以使用它,而不仅仅是我们这些 Vim 书呆子。我说 Perl 是因为这就是我所知道的;其他人会说 python 或 Ruby 或任何他们选择的语言,但无论如何:对于重复使用,Vim 是错误的工具。

但是,有时您只想快速完成某件事,而这可能不会成为一项非常常见的任务。

为了在 Vim 中解决这个问题,我将在 XML 文件旁边的拆分缓冲区中打开 CSV。

  1. 将光标放在 CSV 文件的第一行。
  2. 开始将宏录制到您选择的寄存器中。例如,qa
  3. 执行一个通用命令,该命令将始终将光标放在要删除的 SKU 上,无论您在哪一行。
  4. yiw(或其他一些拉动整个 SKU 的命令)。
  5. <C-W>w将窗口切换到 XML 文件。
  6. :g#<C-R>0启动 :g 命令并将 SKU 作为模式插入。如果存在误报,您可能需要对其进行调整以仅匹配真实的 SKU 行。
  7. 用普通命令完成:g命令,删除整个标签,例如:g#0000001#norm! vatatVd
  8. 返回到 CSV 文件<C-w>p
  9. 移动到 CSV 文件中的下一行j
  10. 使用 停止录制宏q
  11. 测试重复宏一次(例如,@a)。
  12. 如果测试失败,请重复步骤 1-10,直到获得可重复的宏。
  13. 如果(10)按预期工作,请根据需要重复多次,例如9999999@a
于 2013-10-09T03:40:56.800 回答