我有一个包含对象的大型XML文档(13MB)(包含产品SKU,名称等的产品)。
对于每个应从我的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”之类的值。我想找到任何包含该值的产品,并将其删除 - 同时保持其他产品不受影响。
答案 0 :(得分:2)
好的,首先:如果我不止一次这样做,那么我会以一种完全自动化的方式为我做一个漂亮的Perl脚本。然后其他人也可以使用它,而不仅仅是我们的Vim书呆子。我说Perl,因为这就是我所知道的;其他人会说python或Ruby或者他们所选择的语言,但是无论如何:对于重复使用,Vim是错误的工具。
然而,有时你只是想快速完成某件事,这可能不会是一项非常普遍的任务。
要在Vim中解决这个问题,我会在XML文件旁边的分割缓冲区中打开CSV。
qa
yiw
(或其他一些命令来拉动整个SKU)。<C-W>w
将窗口切换为XML文件。:g#<C-R>0
启动a:g命令并插入SKU作为模式。如果存在误报,您可能需要调整此选项以仅匹配真实的SKU行。:g
命令以删除整个标记,例如:g#0000001#norm! vatatVd
<C-w>p
j
q
停止录制宏。@a
)。9999999@a
答案 1 :(得分: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!)并在收到输入后清除提示。
答案 2 :(得分:2)
嗯,这是一个XSLT 2.0解决方案:
<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>
似乎比@ Ben的解决方案简单得多,而且速度要快得多。
可能需要进行一些调整,因为我不清楚CSV文件的格式。