【问题标题】:PHP XPath. Convert complex XML to arrayPHP XPath。将复杂的 XML 转换为数组
【发布时间】:2015-07-14 09:27:50
【问题描述】:

在尝试了三天后,我不得不放弃。这是从 1 dB 的意大利法律导出的巨大 XML 的摘录。我想将此 XML 转换为 PHP 数组,因为目标是使用该数组构建格式化的 Word 文档,使用 PHP 类作为 PHP2RTF。

<CodiceRegionale>
    <sommario>
        <elementoCapitolo>CAP a1</elementoCapitolo>
        <elementoCapitoloDescr>
        </elementoCapitoloDescr>
        <elementoSommarioLegge>
             <elementoTesto>1.1 Legge</elementoTesto>
        </elementoSommarioLegge>
    </sommario>
    <LeggeRegionale id="urn:nir:2014-12-12;26" xmlns="http://www.normeinrete.it/nir/2.1/">
         <elementoSommario xmlns="">
             <elementoCapitolo>CAP a1</elementoCapitolo>
             <elementoCapitoloDescr>
             </elementoCapitoloDescr>
             <elementoSettore />
             <elementoSettoreDescr />
         </elementoSommario>
         <intestazione>Lex 12 2014, n. 26.</intestazione>
             <articolato>
                 <articolo id="art41" xmlns="http://www.normeinrete.it/nir/2.1/">
                     <num>Art. 41</num>
                     <rubrica>(Riforma della finanza locale)</rubrica>
                     <comma id="art41-com1">
                          <num>1. </num>
                          <alinea>Al fine di supportare...</alinea>
                          <el id="art41-com1-let_a">
                              <num>a) </num>
                              <corpo>definizione di...</corpo>
                          </el>
                          <el id="art41-com1-let_b">
                               <num>b) </num>
                               <corpo>coordinamento della...</corpo>
                           </el>
                           <el id="art41-com1-let_c">
                               <num>c) </num>
                               <corpo>definizione delle...</corpo>
                           </el>
                           <el id="art41-com1-let_d">
                               <num>d) </num>
                               <corpo>la disciplina...</corpo>
                           </el>
                      </comma>
                      <comma id="art41-com2">
                           <num>2. </num>
                           <alinea>La revisione di...</alinea>
                           <el id="art41-com2-let_a">
                               <num>a) </num>
                               <corpo>
                                    razionalizzazione e...
                                    <rif xlink:href="urn:nir:stato:legge:2010-12-13;220#art1-com154" xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink">articolo 1, comma 154, della legge 13 dicembre 2010, n. 220</rif>
                                    (Legge di stabilità 2011);
                               </corpo>
                           </el>
                           <el id="art41-com2-let_b">
                               <num>b) </num>
                               <corpo>
                                    applicazione dei...
                                    <rif xlink:href="urn:nir:stato:costituzione:1947-12-27#art119" xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink">articolo 119 della Costituzione</rif>
                                    , nonché del principio...
                               </corpo>
                           </el>
                           <el id="art41-com2-let_c">
                               <num>c) </num>
                               <corpo>valorizzazione...</corpo>
                           </el>
                           <el id="art41-com2-let_d">
                               <num>d) </num>
                               <corpo>previsione di...</corpo>
                           </el>
                           <el id="art41-com2-let_e">
                               <num>e) </num>
                               <corpo>valorizzazione del...</corpo>
                           </el>
                           <el id="art41-com2-let_f">
                               <num>f) </num>
                               <corpo>previsione di...</corpo>
                           </el>
                       </comma>
                       <comma id="art41-com3">
                           <num>3. </num>
                           <corpo>La revisione normativa...</corpo>
                       </comma>
                       <comma id="art41-com4">
                           <num>4. </num>
                           <corpo>I disegni di...</corpo>
                       </comma>
                  </articolo>
                  <articolo id="art42" xmlns="http://www.normeinrete.it/nir/2.1/">
                      <num>Art. 42</num>
                      <rubrica>(Supporto finanziario regionale agli enti locali)</rubrica>
                      <comma id="art42-com1">
                          <num>1. </num>
                          <corpo>Il supporto...</corpo>
                      </comma>
                      <comma id="art42-com2">
                          <num>2. </num>
                          <corpo>Per le finalità di...</corpo>
                      </comma>
                      <comma id="art42-com3">
                          <num>3. </num>
                          <corpo>Gli incentivi regionali...</corpo>
                      </comma>
                      <comma id="art42-com4">
                          <num>4. </num>
                          <corpo>
                                In attuazione...
                                <rif xlink:href="urn:nir:stato:decreto.legislativo:1997-01-02;9#art9" xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink">articolo 9 ...</rif>
                                (Norme di attuazione dello
                                <rif xlink:href="urn:nir:regione.friuli.venezia.giulia:statuto:" xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink">statuto</rif>
                                speciale...
                          </corpo>
                      </comma>
                      <comma id="art42-com5">
                          <num>5. </num>
                          <corpo>Le modalità...</corpo>
                      </comma>
                  </articolo>
             </articolato>
        </LeggeRegionale>
        <LeggeRegionale id="urn:nir:2015-05-22;12" xmlns="http://www.normeinrete.it/nir/2.1/">
            <elementoSommario xmlns="">
                <elementoCapitolo>CAP a7</elementoCapitolo>
                <elementoCapitoloDescr>
                </elementoCapitoloDescr>
                <elementoSettore />
                <elementoSettoreDescr />
            </elementoSommario>
            <intestazione>Lex 22 2015 n. 12...</intestazione>
            <articolato>
                <articolo id="art6">
                    <num>Art. 6</num>
                    <rubrica>(Regolamento interno del CAL)</rubrica>
                    <comma id="art6-com1">
                        <num>1. </num>
                        <corpo>Il CAL approva...</corpo>
                    </comma>
                    <comma id="art6-com2">
                        <num>2. </num>
                        <alinea>Il regolamento...</alinea>
                        <el id="art6-com2-let_a">
                            <num>a) </num>
                            <corpo>l'elezione...</corpo>
                        </el>
                        <el id="art6-com2-let_b">
                            <num>b) </num>
                            <corpo>le funzioni degli organi del CAL;</corpo>
                        </el>
                        <el id="art6-com2-let_c">
                            <num>c) </num>
                            <corpo>la costituzione...</corpo>
                        </el>
                        <el id="art6-com2-let_d">
                            <num>d) </num>
                            <corpo>la programmazione...</corpo>
                        </el>
                        <el id="art6-com2-let_e">
                            <num>e) </num>
                            <corpo>i casi nei...</corpo>
                        </el>
                        <el id="art6-com2-let_f">
                            <num>f) </num>
                            <corpo>le modalità di...</corpo>
                        </el>
                    </comma>
                    <comma id="art6-com3">
                        <num>3. </num>
                        <corpo>Il regolamento è pubblicato...</corpo>
                    </comma>
               </articolo>
          </articolato>
     </LeggeRegionale>
     <LeggeRegionale id="urn:nir:2014-12-12;26" xmlns="http://www.normeinrete.it/nir/2.1/">
         <elementoSommario xmlns="">
             <elementoCapitolo>CAP a8</elementoCapitolo>
             <elementoCapitoloDescr>
             </elementoCapitoloDescr>
             <elementoSettore />
             <elementoSettoreDescr />
         </elementoSommario>
         <intestazione>Lex 12 2014, n. 26....</intestazione>
         <articolato>
             <articolo id="art17">
                  <num>Art. 17</num>
                  <rubrica>(Piano dell'Unione)</rubrica>
                  <comma id="art17-com1">
                      <num>1. </num>
                      <corpo>Il Piano dell'Unione...</corpo>
                  </comma>
                  <comma id="art17-com2">
                      <num>2. </num>
                      <corpo>
                                            Il Piano ...
                                            <rif xlink:href="urn:nir:stato:decreto.legislativo:2000;267#art170" xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink">articolo 170 ...</rif>
                                            .
                      </corpo>
                 </comma>
                 <comma id="art17-com3">
                     <num>3. </num>
                     <corpo>Il Piano dell'Unione...</corpo>
                 </comma>
                 <comma id="art17-com4">
                     <num>4. </num>
                     <corpo>La relazione annuale...</corpo>
                 </comma>
            </articolo>
        </articolato>
   </LeggeRegionale>
   <LeggeRegionale id="urn:nir:regione.friuli.venezia.giulia:legge:2014-12-12;26" xmlns="http://www.normeinrete.it/nir/2.1/">
       <elementoSommario xmlns="">
           <elementoCapitolo>CAP a14</elementoCapitolo>
           <elementoCapitoloDescr>
           </elementoCapitoloDescr>
           <elementoSettore />
           <elementoSettoreDescr />
       </elementoSommario>
       <intestazione>Lex 12 dicembre 2014, n. 26 ....</intestazione>
       <articolato>
           <articolo id="art5">
               <num>Art. 5</num>
               <rubrica>(Unioni territoriali intercomunali)</rubrica>
               <comma id="art5-com1">
                   <num>1. </num>
                   <corpo>Le Unioni territoriali...</corpo>
               </comma>
               <comma id="art5-com2">
                   <num>2. </num>
                   <corpo>
                                L'Unione ha...
                                <rif xlink:href="urn:nir:stato:decreto.legislativo:2000-08-18;267#art32" xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink">articolo 32...</rif>
                                (Testo unico delle leggi sull'ordinamento degli enti locali).
                   </corpo>
              </comma>
         </articolo>
    </articolato>
</LeggeRegionale>

我正在尝试构建的数组应该类似于以下内容:

Array
(
    [LeggeRegionale] => Array
        (
            [intestazione] => Lex 12 2014, n. 26.
            [articolato] => Array
                (
                    [num] => Art. 41
                    [articolo] => Array
                        (
                            [rubrica] => (Riforma della finanza locale)
                            [commi] => Array
                                (
                                    [num_alinea] => 1. Al fine di supportare...
                                    [el] => Array
                                        (
                                            [num_corpo] => a) definizione di...
                                            [num_corpo] => b) coordinamento della...
                                        )
                                    [num_alinea] => 2. La revisione di...
                                 )
                          )
                     [num] => Art. 42
                     ...
                  )
           )
   )

有了这段代码,我可以读取所有的 XML,但它绝对没用:

$results = array();
$query = '//a:LeggeRegionale';
$result = $xpath->query($query);

$results = array();

for($i=0; $i < $result->length; $i++) {
    $results[$i] = $result->item($i)->nodeValue;
    echo $results[$i]."<BR><BR>";
}
echo "<BR>";

这段代码确实返回了一些结构化的东西(尽管它不是我要查找的数组),但我不明白为什么当我使用 foreach loop 时它只返回最后一次出现的 LeggeRegionale

foreach ($result as $entry) {

    $result = [
        'intestazione' => $xpath->query('//a:LeggeRegionale')->item($i)->nodeValue,
        'articoli' => array(
                        'numero'    => $xpath->query('//a:articolato/a:articolo/a:num')->item($i)->nodeValue,
                        'rubrica'   => $xpath->query('//a:articolato/a:articolo/a:rubrica')->item($i)->nodeValue,
                        'commi' => array(
                                    'numero'    => $xpath->query('//a:articolato/a:articolo/a:comma/a:num')->item($i)->nodeValue,
                                    'corpo'     => $xpath->query('//a:articolato/a:articolo/a:comma/a:corpo|//a:articolato/a:articolo/a:comma/a:alinea')->item($i)->nodeValue,
                                    'lettere'   => array(
                                                    'lettera'   => $xpath->query('//a:articolato/a:articolo/a:comma/a:el')->item($i)->nodeValue,
                                    ),
                        ),
        ),
    ];
    array_push($a, $result);
    $i++;
}

我认为有一种更好的方法 - 感谢 XPath - 读取所有后代而不是为每个 XML 级别编写 foreach loop

【问题讨论】:

  • 也许您可以使用一些在线工具将 XML 转换为 JSON 并进行简单的 json_decode?​​span>
  • 是否要将解析后的 XML 的所有元素包含在 PHP 数组中?还是只有某些?如果有,有哪些?如果要将 XML 的元素名称映射到 PHP 数组的键名称,对于多个同名元素,您希望得到哪个结果,如 LeggeRegionale ?您想要的结果有一个键 [LeggeRegionale],您要提取这几个元素中的哪个元素?
  • 你可能在我的伪array中看到,从标签LeggeRegionale开始我想保留intestazione这是法律的标题,那么法律有很多文章articolo(由 ids 标识)具有编号 num 和标题 rubrica。每个articolo 都有段落comma,其内容是alinea(或者有时corpo 我注意到了)。碰巧alinea 可能有子段落显示为el。每个法律LeggeRegionale 都应该是与 XML 不同的数组条目。
  • 为什么是数组,为什么不从 XML 中读取数据?
  • 因为我想用数组来创建一个Word/RTF文件。数组对我来说会更容易管理,因为我发现阅读这个 XML 非常困难。

标签: php arrays xml xpath


【解决方案1】:

将复杂的 XML 转换为数组将导致 ... 成为一个复杂的数组。您发现 XML 难以阅读,并且您认为数组对您来说更容易,因此数组必须是解决方案。但实际上 XML 非常适合 PHP 中的树解析。数组不可访问。例如,您不能对数组运行 xpath 查询。

对于数组,您的伪数组中存在重复键的错误。结构看起来更像:

Array
(
    [LeggeRegionale] => Array
        (
            [0] => Array
                (
                    [intestazione] => Lex 12 2014, n. 26.
                    [articolato] => Array
                        (
                            [articolo] => Array
                                (
                                    [0] => Array
                                        (
                                            [num] => Art. 41
                                            [rubrica] => (Riforma della finanza locale)
                                            [commi] => Array
                                                (
                                                    [0] => Array
                                                        (
                                                            [num_alinea] => 1. Al fine di supportare...
                                                            [num_corpo] => Array
                                                                (
                                                                    [0] => a) definizione di...
                                                                    [1] => b) coordinamento della...
                                                                    [2] => c) definizione delle...
                                                                    [3] => d) la disciplina...
                                                                )

                                                        )

                                                    [1] => Array
                                                        (
                                                            [num_alinea] => 2. La revisione di...
                                                            [num_corpo] => Array
                                                                (
                                                                    [0] => a) razionalizzazione e... articolo 1, comma 154, della legge 13 dicembre 2010, n. 220 (Legge di stabilità 2011);
                                                                    [1] => b) applicazione dei... articolo 119 della Costituzione , nonché del principio...
                                                                    [2] => c) valorizzazione...
                                                                    [3] => d) previsione di...
                                                                    [4] => e) valorizzazione del...
                                                                    [5] => f) previsione di...
                                                                )

...

这已经进行了一些优化(您可以忽略编码错误的字符,这是复制和粘贴错误)。

您可能希望使用一个库,它可以更轻松地直接通过 xpath 查询子节点。我已经给出了一个答案,在 use DOMXPath and function query php 中显示了一个小而快速的示例,您需要 add namespace support 来解决这个问题。然后,您需要处理数组构建,这实际上非常复杂:

$doc = new DOMDocument();
$doc->load('example.xml');

/* DOMBLAZE II XMLNS */ $doc->registerNodeClass("DOMElement", "DOMBLAZE"); # ...

/** @var $root DOMBLAZE */
$root = $doc->documentElement;
$root()->registerNamespace('a', 'http://www.normeinrete.it/nir/2.1/');

$array = [];
foreach ($root('a:LeggeRegionale') as $leggioRegionale) {
    $entry                 = [];
    $entry['intestazione'] = $leggioRegionale('string(./a:intestazione)');
    $articolato            = [];
    foreach ($leggioRegionale('a:articolato/a:articolo') as $articolo) {
    }
    $array[] = $entry;
}

print_r($array);

这个例子(显然)是不完整的。

另外,我尝试在定义“数组”的 XML 中写下 xpath 表达式。然后可以将其与定制的 SimpleXMLElement 一起使用,以根据定义递归地构建数组:

$doc = new DOMDocument();
$doc->load('example.xml');

$buffer = <<<XML
<xmlarray>
    <xml>
        <namespace prefix="a" uri="http://www.normeinrete.it/nir/2.1/"/>
    </xml>
    <array>
        <LeggeRegionale expr="a:LeggeRegionale">
            <intestazione expr="string(a:intestazione)"/>
            <articolato expr="a:articolato">
                <articolo expr="a:articolo">
                    <num expr="string(a:num)"/>
                    <rubrica expr="string(a:rubrica)"/>
                    <commi expr="a:comma">
                        <num_alinea expr="concat(a:num, a:alinea)"/>
                        <el expr="a:el" alias="num_corpo">
                            <num_corpo expr="normalize-space(concat(a:num, a:corpo))" cast="string"/>
                        </el>
                    </commi>
                </articolo>
            </articolato>
        </LeggeRegionale>
    </array>
</xmlarray>
XML;

$xmlArray = new XmlArrayElement($buffer);
$xmlArray->assignDocument($doc);
print_r($xmlArray->toArray());

这确实有效地产生了答案开头的数组。

当然,这对您来说现在看起来像是超级解决方案,但它所做的只是将 XML 树包装到另一棵树中,这次是在一个数组中。 XmlArrayElement is not part of the example in the answer but in a gist

利用递归动态创建另一个 XML 文档可能会更好。

在您的情况下,XSLT 也值得考虑,它在技术上是为此而设计的。您可以直接在 HTML 文档中进行转换。 HTML 文档比 RTF 文档更便于移植,并且有现有的工具可以将它们转换为 RTF 以及其他文档。

【讨论】:

  • 非常感谢您抽出宝贵的时间。是的,我意识到我正在考虑的数组处理起来会非常复杂(可能与 XML 一样复杂),但至少我知道如何着手处理它。我还将尝试通过即时创建另一个 XML 或使用 XSLT。
  • 另一种选择是采用代码并使其返回 SimpleXMLElement 而不是数组。
  • 我正在尝试您的最后一个代码:我在您的脚本中添加了您的优秀类 XmlArrayElement,XML 被加载为外部文件(这与我的原始帖子相同)但我不断收到 @987654327 @.
  • 最外层的 xpath 表达式 ("a:LeggeRegionale") 与您的文件的任何节点都不匹配。我在示例中的 example.xml 是您问题中的部分,我刚刚关闭了仍然打开的标签,否则它将是无效的 XML。 -- 也许你有一个不同的根元素(例如更深),所以“//a:LeggeRegionale”已经可以做到了。
  • 是的,LeggeRegionale 不是根标签。更改为&lt;LeggeRegionale expr="//a:LeggeRegionale"&gt; 并完美运行。
猜你喜欢
  • 2017-01-04
  • 1970-01-01
  • 1970-01-01
  • 2011-12-25
  • 2015-09-03
  • 2016-10-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多