我试图在我的所有xml文件中以递增的方式在TEXT_VALUE
字段的值前加一个数字,只有标签名为" TRANSL"使用 ID ="示例" 。
目前我手动完成,但由于我有几千个,我想我应该以编程方式进行。
这是初始版本:
<TRANSL ID="Example">
<TRANSCIPT>
<REF_TEXT TEXT_ID="a680" TXT_TM="a24">
<TEXT_VALUE>this is an example</TEXT_VALUE>
</REF_TEXT>
</TRANSCIPT>
<TRANSCIPT>
<REF_TEXT TEXT_ID="a681" TXT_TM="a25">
<TEXT_VALUE>another example</TEXT_VALUE>
</REF_TEXT>
</TRANSCIPT>
<TRANSCIPT>
<REF_TEXT TEXT_ID="a682" TXT_TM="a26">
<TEXT_VALUE>third example</TEXT_VALUE>
</REF_TEXT>
</TRANSCIPT>
</TRANS>
以下是它应该是这样的编辑版本:
<TRANSL ID="Example">
<TRANSCIPT>
<REF_TEXT TEXT_ID="a680" TXT_TM="a24">
<TEXT_VALUE>1-this is an example</TEXT_VALUE>
</REF_TEXT>
</TRANSCIPT>
<TRANSCIPT>
<REF_TEXT TEXT_ID="a681" TXT_TM="a25">
<TEXT_VALUE>2-another example</TEXT_VALUE>
</REF_TEXT>
</TRANSCIPT>
<TRANSCIPT>
<REF_TEXT TEXT_ID="a682" TXT_TM="a26">
<TEXT_VALUE>3-third example</TEXT_VALUE>
</REF_TEXT>
</TRANSCIPT>
</TRANS>
我该如何以编程方式执行此操作?那里有专业的xml编辑器吗?如果没有,我如何在python,powershell,perl,notepad ++或其他任何其他内容中执行此操作?
这是我在python中作为记事本++插件的脚本:
def increment_replace(match):
return "<TEXT_VALUE>{}".format(str(int(match.group(1))+1))
editor.rereplace(r'\<TEXT_VALUE\>', increment_replace)
但它不起作用......
答案 0 :(得分:3)
要获取position()
元素的当前计数/ <TEXT_VALUE>
,您可以引用父position()
元素的计数/ <TRANSCIPT>
。
将此计数传递给后续模板I used the solution from this SO answer,并将其方法合并到身份模板中,现在传递包含某些值的num
参数。 num
参数在所有<for-each>
元素上方的<TRANSCIPT>
循环中生成,并传递到<apply-templates>
层次结构,以便在TEXT_VALUE
模板中使用(其他任何位置) #39; s被忽略了。)
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<!-- modified identity template -->
<xsl:template match="node()|@*">
<xsl:param name="num" />
<xsl:copy>
<xsl:apply-templates select="node()|@*">
<xsl:with-param name="num" select="$num"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
<xsl:template match="TRANSL">
<xsl:copy>
<xsl:apply-templates select="@*" />
<xsl:for-each select="TRANSCIPT">
<xsl:copy>
<xsl:apply-templates>
<xsl:with-param name="num" select="position()" />
</xsl:apply-templates>
</xsl:copy>
</xsl:for-each>
</xsl:copy>
</xsl:template>
<xsl:template match="TEXT_VALUE[../../../@ID='Example']"> <!-- added after extension of question -->
<xsl:param name="num" />
<xsl:element name="TEXT_VALUE">
<xsl:value-of select="concat($num,'-',text())" />
</xsl:element>
</xsl:template>
</xsl:stylesheet>
修改强>
在评论中扩展了要求后,我在TEXT_VALUE
模板中添加了一个谓词,修改匹配规则,仅选择TEXT_VALUE
个@ID
属性值为&#34}的元素。实施例&#34;
答案 1 :(得分:2)
要使用count(preceding-sibling::*)
使用变体XSLT脚本添加到@ zx485,请使用lxml
考虑以下Python解决方案。作为信息,XSLT是一种转换XML文件的专用语言,可以方便地将初始XML文件操作为最终最终用途格式。
Python是一种通用语言,您可以利用其os
文件系统模块和第三方模块lxml(具有XPath 1.0和XSLT 1.0功能的完全兼容的W3C库)来迭代地使用它创造所需的产出。
XSLT (另存为.xsl文件,以Python格式解析)
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output version="1.0" encoding="UTF-8" indent="yes" method="xml"/>
<xsl:strip-space elements="*"/>
<!-- Identity Transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<!-- Add Incremenet Number to Text -->
<xsl:template match="TEXT_VALUE[ancestor::TRANSL/@ID='Example']">
<xsl:copy>
<xsl:value-of select="concat(count(ancestor::TRANSCIPT/preceding-sibling::TRANSCIPT)+1, '-', text())"/>
</xsl:copy>
</xsl:template>
</xsl:transform>
<强>的Python 强>
import os
import lxml.etree as et
# CHANGE DIRECTORY
os.chdir('/path/to/raw/XML/files')
# LOAD XSLT SCRIPT AND INITIALIZE TRANSFORMER
xslt = et.parse('/path/to/XSLT_Script.xsl')
transform = et.XSLT(xslt)
for file in os.listdir():
if file.endswith('.xml'):
# LOAD SOURCE XML
dom = et.parse(file)
# TRANSFORM TO NEW TREE
newdom = transform(dom)
# SAVE TO FILE (SAME NAME WITH _new SUFFIX)
with open(file.replace('.xml', '_new.xml'), 'wb') as f:
f.write(newdom)