我可以使用XPath或其他类似regex的东西从XML中提取数据吗?


Can I use XPath or something else like a regex to extract data from XML?

我当然可以使用正则表达式来解析XML中的数据。

<?xml version="1.0"?>
<definitions>
  <message name="notificationInput">
    <part name="body" element="xsd:notificationRequest" />
  </message>
  <message name="notificationOutput">
    <part name="body" element="xsd:notificationResponse" />
  </message>
</definitions>

类似

的模式
/<message.*name="(.*)".*part.*name=".*".*element="xsd:(.*)".*<'/message>/sUg

可能会给我想要的数据,这里显示为PHP数组:

array(
  array("notificationInput", "body", "notificationRequest"),
  array("notificationOutput", "body", "notificationResponse")
)

这当然是非常麻烦和容易出错的。

我知道如何使用XPath来查询完整的节点,但我不认为我可以告诉它"我想要属性nameelement从节点/definitions/message/part和每个结果,我也想要属性name从它的父"

现在我想知道是否有某种语言或技术(最好是PHP实现)可以用来指定我想提取的数据。

换句话说,我正在寻找一种或多或少可以配置而不是编程的解决方案,因为我有相当多的类似定义来提取。

您可以使用XPath

//message/@name|//message[@name]/part/@name|//message/part/@element

生成所有所需属性的一维序列(抱歉,这是在Python中):

In [366]: doc.xpath('//message/@name|//message[@name]/part/@name|//message/part/@element')
Out[366]: 
['notificationInput',
 'body',
 'xsd:notificationRequest',
 'notificationOutput',
 'body',
 'xsd:notificationResponse']

,然后使用array_chunk将结果重新排列为3组。(注意,您仍然需要使用一点正则表达式或字符串操作来从notificationResponse中删除xsd:,但这仍然比使用正则表达式解析XML更容易和更健壮。

XPath将收集所有属性,即使每个<message>有多个<part>

这个简短的XPath 1.0表达式选择所有需要的属性节点:

/*//*/@*

然后对于每个选定的节点,你可以使用PHP(我不知道)获得它的字符串值。


如果可以使用XPath 2.0,那么所有需要的值都是通过计算类似的表达式产生的:

/*//*/@*/data(.)

下面是一个简单的XSLT 2.0转换,它只计算上述表达式并输出结果:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="text"/>
  <xsl:template match="/">
    <xsl:sequence select="/*//*/@*/data(.)"/>
  </xsl:template>
</xsl:stylesheet>

当对提供的XML文档应用此转换时:

<definitions>
  <message name="notificationInput">
    <part name="body" element="xsd:notificationRequest" />
  </message>
  <message name="notificationOutput">
    <part name="body" element="xsd:notificationResponse" />
  </message>
</definitions>

生成所需的结果:

notificationInput body xsd:notificationRequest notificationOutput body xsd:notificationResponse

我知道不建议用正则表达式解析html,除非你知道所涉及的字符集是什么,但我发布这个答案,因为它可能对你有用。

对于您提供的示例文本,您可以使用如下的简单正则表达式:
([a-z]+)"
演示工作

Php

代码:

$re = "/([a-z]+)'"/i"; 
$str = "<?xml version='"1.0'"?>'n<definitions>'n  <message name='"notificationInput'">'n    <part name='"body'" element='"xsd:notificationRequest'" />'n  </message>'n  <message name='"notificationOutput'">'n    <part name='"body'" element='"xsd:notificationResponse'" />'n  </message>'n</definitions>"; 
preg_match_all($re, $str, $matches);

然后您可以从$matches抓取捕获的内容。

匹配信息:

MATCH 1
1.  [53-70] `notificationInput`
MATCH 2
1.  [89-93] `body`
MATCH 3
1.  [108-127]   `notificationRequest`
MATCH 4
1.  [162-180]   `notificationOutput`
MATCH 5
1.  [199-203]   `body`
MATCH 6
1.  [218-238]   `notificationResponse`