使用REGEX使用脚本检查XML节点

时间:2011-05-04 15:46:49

标签: python xml bash lxml

这里有点问题,基本上我有一个我使用GET的网址。 例如111.244.25.633/Data.XML(不要担心IP,它只是为设备做的),它返回一个XML文件。

在Data.XML中,我们有一些节点和子节点。 (就像我想的一棵树) 例如,整个数据封装如下:(缩进意味着它是上面的子节点......等等)

 <Data>
   <DeviceData>
       <Info>
        <SerialNumber>154236</SerialNumber>
        <Ethernet>Y</Ethernet>
        <Wireless>N</Wireless>
        <Mac>00:25:F6:25:K9</Mac>
       </Info>
   </DeviceData>
 </Data>

基本上,我想使用正则表达式来检查子节点(就像我想确保序列号是一个6位数字,而不是别的东西)

子节点总是被称为相同的东西(如序列号,设备数据,数据.......等)

什么是最容易使用的扩展/语言?我知道基本的python和bash,我非常了解C / C ++ ......但这对我来说似乎更像是一个脚本任务。

有什么想法吗?

编辑:我忘了添加:我可能有更多或更少的XML标签(比如某些设备有更多设置等)所以我会在脚本中挑选出特定的标签,而不是查看每个标签......因为有些人可能比其他人更多或更少。

3 个答案:

答案 0 :(得分:3)

请参阅此回复:Regular Expressions to parse template tags in XML

您项目的演示......

from xml.etree import ElementTree
import re

def proper_SN(elem):
    if re.search('\d{6}', elem.text):
        return True
    return False

tree = ElementTree.parse('data.xml')
rows = tree.getiterator('SerialNumber')
for row in rows:
    print "SerialNumber: %s Passed = %s" % (row.text, proper_SN(row))

运行此...

[mpenning@hotcoffee tmp]$ python parse.py 
SerialNumber: 154236 Passed = True
[mpenning@hotcoffee tmp]$

修改

我不确定XML可能会如何变化...假设您更改了DeviceData元素...

 <Data>
   <DeviceData>
       <Info>
        <SerialNumber>154236</SerialNumber>
        <EngineVersion>12.0.4.13</EngineVersion>
        <MediaType>100BaseT</MediaType>
        <Ethernet>Y</Ethernet>
        <Wireless>N</Wireless>
        <Mac>00:25:F6:25:K9</Mac>
       </Info>
   </DeviceData>
 </Data>

使用简化的脚本......

from xml.etree import ElementTree
import re

def proper_SN(elem):
    if re.search('\d{6}', elem.text):
        return True
    return False

tree = ElementTree.parse('data.xml')
serial = tree.find('DeviceData/Info/SerialNumber').text
engine = tree.find('DeviceData/Info/EngineVersion').text
media = tree.find('DeviceData/Info/MediaType').text

if proper_SN:
    serstr = "good"
else:
    serstr = "bad"

print "Found a %s serial number (%s), with engine %s and media %s" % (serstr, serial, engine, media)

我得到了

[mpenning@hotcoffee tmp]$ python parse.py 
Found a good serial number (154236), with engine 12.0.4.13 and media 100BaseT
[mpenning@hotcoffee tmp]$

答案 1 :(得分:2)

使用XML解析模块,如lxmlElementTree(在Python stdlib中),而不是正则表达式。然后,您可以使用正则表达式来验证序列号。以下是使用ElementTree执行此操作的一些代码:

import re
import xml.etree.ElementTree

tree = xml.etree.ElementTree.XML(r'''
 <Data>
   <DeviceData>
       <Info>
        <SerialNumber>154236</SerialNumber>
        <Ethernet>Y</Ethernet>
        <Wireless>N</Wireless>
        <Mac>00:25:F6:25:K9</Mac>
       </Info>
   </DeviceData>
 </Data>
''')

serial = tree.find('DeviceData/Info/SerialNumber')
print serial.text

if re.match('\d{6}', serial.text.strip()):
    print 'OK'
else:
    print 'ERROR'

答案 2 :(得分:2)

如果您更喜欢使用更具声明性的编写规则的方式(与python&amp; lxml的程序方法相比),您也可以使用XSLT 2.0。

类似的东西:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs" version="2.0">

  <xsl:output method="text" />

  <xsl:template match="SerialNumber[matches( normalize-space(.), '^\d{6}$')]" >
    <xsl:value-of select="." /> Passes.
  </xsl:template>

  <xsl:template match="SerialNumber[not( matches( normalize-space(.), '^\d{6}$'))]" >
    <xsl:value-of select="." /> Fails.
  </xsl:template>

  <xsl:template match="text()">
    <!-- override default template, output nothing -->
  </xsl:template>

</xsl:stylesheet>

将输出:

154236通过。

X154236失败。

如果您有很多要检查的规则,也许您应该查看XML Schema语言 例如Relax NGSchematron。模式是一种为XML文档编写语法的方法,该文档比DTD更具表现力。您编写声明性规则并使用模式语言,并且处理器编写将根据模式验证XML的XSLT代码。