Проверка узлов XML с помощью скрипта с использованием REGEX - PullRequest
1 голос
/ 04 мая 2011

Немного проблем здесь, в основном у меня есть веб-адрес, с которым я использую 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 ++ ... но для меня это больше похоже на задачу сценариев.

Есть идеи?

edit: я забыл добавить: у меня может быть БОЛЬШЕ или меньше тегов XML (например, у некоторых устройств больше настроек и тому подобное), поэтому я бы выбирал конкретные скрипты, а не КАЖДЫЙ отдельный тег ... . поскольку у некоторых может быть больше или меньше, чем у других.

Ответы [ 3 ]

3 голосов
/ 04 мая 2011

Пожалуйста, посмотрите этот ответ: Регулярные выражения для анализа тегов шаблонов в 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]$
2 голосов
/ 04 мая 2011

Вы также можете сделать это с XSLT 2.0, если вы предпочитаете более декларативный способ написания ваших правил (по сравнению с процедурным подходом с python & lxml).

Что-то вроде:

<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 Fails.

Если вам нужно проверить много правил, возможно, вам стоит взглянуть на языки XML-схемы. как Relax NG или Schematron . Схема - это способ написания грамматики для XML-документа, который более выразителен, чем DTD. Вы пишете декларативные правила и на языке схемы, а процессор пишет код XSLT, который будет проверять XML на соответствие схеме.

2 голосов
/ 04 мая 2011

Используйте модули синтаксического анализа XML, такие как lxml или ElementTree (в 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'
...