PHP simpleXML根据值

时间:2016-11-24 22:48:19

标签: php xml simplexml

我有以下XML代码:

<administration>
    <notes>
        <note>
            <id>12312312</id>
            <name>Lorem Ipsum</name>
            <reference>Target Value - 1</reference>
        </note>
        <note>
            <id>12312365</id>
            <name>Lorem Ipsum</name>
            <references>
                <code>Dolor it se met.</code>
                <code>Target Value - 2</code>
            </references>
        </note>
        <note>
            <id>12375512</id>
            <name>Target Value - 3</name>
            <reference>S</reference>
        </note>
    </notes>
    <accounting>
        <ledgers>
            <ledger>
                <debits>
                    <debit>
                        <description>Target Value - 4</description>
                        <amount>5467.32</amount>
                    </debit>
                    <debit>
                        <description>My Debit</description>
                        <amount>5467.32</amount>
                        <tags>
                            <tag>Target Value - 5</tag>
                        </tags>
                    </debit>
                </debits>
                <credits>
                    <credit>
                        <title>Target Value - 6</title>
                        <amount>873.00</amount>
                    </credit>
                    <credit>
                        <description>Target Value - 7</description>
                        <amount>23454.12</amount>
                    </credit>
                </credits>
            </ledger>
        </ledgers>
    </accounting>
</administration>

我试图获取一个PHP数组,该数组只包含具有包含此字符串值的节点的值:&#34;目标值&#34;。 这必须以递归的方式完成,使用XML解析器(我尝试使用SimpleXML,但我不熟悉它)。

Up&#39;到现在为止,我一直在尝试使用SimpleXmlIterator和foreach-和for-loops来实现这一目标,但我似乎无法检查节点值是否包含&#34 ;目标价值&#34;。

编辑:通过手动引用到达目标节点不是我想要的,如果我是,那就没有问题

有没有办法实现这个目标?

编辑:

以下是我上次尝试的代码:     

function sxiToArray($sxi)
{
    $a = array();
    for( $sxi->rewind(); $sxi->valid(); $sxi->next() )
    {
        if(!array_key_exists($sxi->key(), $a))
        {
            $a[$sxi->key()] = array();
        }
        if($sxi->hasChildren())
        {
            if (strpos((string)$sxi->current(), "Target Value"))
                $a[$sxi->key()][] = sxiToArray($sxi->current());
        }
        else
        {
            if (strpos((string)$sxi->current(), "Target Value"))
                $a[$sxi->key()][] = strval($sxi->current());
        }
    }
    return $a;
}

$xmlArray = xml2array('../Document.xml');
print_r($xmlArray);

运行后会得到以下结果:

Array([notes] =&gt; Array()[accounting] =&gt; Array())

2 个答案:

答案 0 :(得分:0)

为什么不为“目标价值”尝试str_pos()?我不知道你如何遍历XML,但你可以做类似的事情:

if(str_pos($node, "Target value"){
    //do whatever
}

这将告诉您是否任何节点至少包含该特定字符串。

答案 1 :(得分:0)

不必以递归方式完成。您可以使用Xpath。 Xpath使用位置路径作为表达式的一部分。路径使用不同的轴 - 其中一个是后代。它&#34;忽略&#34;筑巢。 Xpath允许您使用条件。

  • 获取文档中的任何元素节点
    //*
  • 有一个文本节点作为孩子 //*[./text()]
  • ,文本节点包含字符串&#34;目标值&#34;
    //*[./text()[contains(., "Target Value")]]

把它放在一起是一段相当小的代码:

$administration = new SimpleXMLElement($xml);
$nodes = $administration->xpath('//*[./text()[contains(., "Target Value")]]');

foreach ($nodes as $node) {
  var_dump($node->getName(), (string)$node);
}

输出:

string(9) "reference"
string(16) "Target Value - 1"
string(4) "code"
string(16) "Target Value - 2"
string(4) "name"
string(16) "Target Value - 3"
string(11) "description"
string(16) "Target Value - 4"
string(3) "tag"
string(16) "Target Value - 5"
string(5) "title"
string(16) "Target Value - 6"
string(11) "description"
string(16) "Target Value - 7"

使用DOM,它看起来不会有太大不同:

$document = new DOMDocument();
$document->loadXml($xml);
$xpath = new DOMXpath($document);

$nodes = $xpath->evaluate('//*[./text()[contains(., "Target Value")]]');

foreach ($nodes as $node) {
  var_dump($node->localName, $node->textContent);
} 
相关问题