如果gsed
(基于正则表达式的)解决方案提取正确的 xml 文本,那么您可以扩展解决方案以包括开始/结束位置,假设<myelement>
未嵌套:
$ perl -0777 -ne 'print "start: $-[0], end: $+[0], xml: {{{$&}}}\n" while /<myelement>.*?<\/myelement>/gs' < input > output
输入
some arbitrary text
A well-formed xml:
<myelement>
... xml here
</myelement>
some arbitrary text follows more elements: <myelement>... xml</myelement> the end
start: 40, end: 77, xml: {{{<myelement>
... xml here
</myelement>}}}
start: 122, end: 152, xml: {{{<myelement>... xml</myelement>}}}
这是一个 Python 解决方案,它构建正则表达式以匹配纯文本中的一些 xml 元素,假设每个根元素没有嵌套,并且它不在基于
Python 中的匹配模式的注释或 cdata 中:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import re
import sys
from xml.etree import ElementTree as etree
# build regex that matches xml element
# xml_element = start_tag <anything> end_tag
# | self_close_tag
xml_element = '(?xs) {start_tag} (?(self_close) |.*? {end_tag})'
# start_tag = '<' name *attr '>'
# self_close_tag = '<' name *attr '/>'
ws = r'[ \t\r\n]*' # whitespace
start_tag = '< (?P<name>{name}) {ws} (?:{attr} {ws})* (?P<self_close> / )? >'
end_tag = '</ (?P=name) >'
name = '[a-zA-Z]+' # note: expand if necessary but the stricter the better
attr = '{name} {ws} = {ws} "[^"]*"' # match attribute
# - fragile against missing '"'
# - no “'” support
assert '{{' not in xml_element
while '{' in xml_element: # unwrap definitions
xml_element = xml_element.format(**vars())
# extract xml from stdin
all_text = sys.stdin.read()
for m in re.finditer(xml_element, all_text):
print("start: {span[0]}, end: {span[1]}, xml: {begin}{xml}{end}".format(
span=m.span(), xml=m.group(), begin="{{{", end="}}}"))
# assert well-formness of the matched xml text by parsing it
etree.XML(m.group())
在匹配更多种类的 xml 元素和避免误报之间需要权衡取舍。
一个更健壮的解决方案应该考虑输入的格式,即 QUnit,Javadoc 词法分析器/解析器可以帮助提取 xml 片段,这些片段可以稍后输入 xml 解析器。
谨防:
为什么不能使用正则表达式来解析 HTML/XML:通俗易懂的正式解释
您能否提供一些示例说明为什么使用正则表达式难以解析 XML 和 HTML?