Проверка узлов XML с помощью скрипта с использованием REGEX

1

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

В принципе, я хочу использовать регулярные выражения для проверки Subnodes (например, я хотел бы убедиться, что Serial Number - это 6-значное число, а не что-то еще)

Подносы всегда будут называться одним и тем же (например, серийный номер, данные устройства, данные....... и т.д.)

Какое хорошее расширение/язык, который будет проще всего использовать для этого? Я знаю базовый python и bash, я хорошо знаю C/С++... но для меня это похоже на задачу сценариев.

Любые идеи?

edit: Я забыл добавить: у меня могут быть БОЛЬШЕ или меньше XML-тегов (например, у некоторых устройств больше настроек и т.д.) Поэтому я бы выбрал конкретные в script, не глядя ни на один тег.... поскольку некоторые могут иметь больше или меньше других.

  • 0
    пожалуйста, посмотрите пример в моем ответе
Теги:
lxml

3 ответа

3
Лучший ответ

См. этот ответ: Регулярные выражения для анализа тегов шаблонов в 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>

Использование упрощенного script...

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]$
  • 0
    Будет ли это работать, если я скажу, что "МОЖЕТ" иметь больше узлов, чем указано в списке, но я хочу проверить только несколько?
  • 0
    @ Саурон, я сделал несколько предположений, и по твоему описанию трудно понять ... если ты можешь предоставить конкретные сведения о том, как могут изменяться узлы XML, я могу сказать наверняка
Показать ещё 4 комментария
2

Вы также можете сделать это с помощью 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 Не удается.

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

2

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню