xml批量文件编辑器按数字递增

时间:2017-03-18 13:25:38

标签: python regex xml xml-parsing auto-increment

我试图在我的所有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)

但它不起作用......

2 个答案:

答案 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)