PHP SimpleXML 对象中的属性消失了?

发布于 2024-12-21 22:36:29 字数 319 浏览 0 评论 0 原文

我需要返回一个转换为 JSON 对象的 SimpleXML 对象,以便在 JavaScript 中使用它。问题是任何对象上都没有具有值的属性。

举个例子:

<customer editable="true" maxChars="9" valueType="numeric">69236</customer>

在 SimpleXML 对象中变成:

"customer":"69236"

@attributes 对象在哪里?

I need to return a SimpleXML object converted as a JSON object to work with it in JavaScript. The problem is that there are no attributes on any object with a value.

As an example:

<customer editable="true" maxChars="9" valueType="numeric">69236</customer>

becomes in the SimpleXML object:

"customer":"69236"

Where is the @attributes object?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

合约呢 2024-12-28 22:36:29

这多次让我发疯。当 SimpleXML 遇到只有文本值的节点时,它会删除所有属性。我的解决方法是在使用 SimpleXML 解析之前修改 XML。使用一些正则表达式,您可以创建一个包含实际文本值的子节点。例如,在您的情况下,您可以将 XML 更改为:

<customer editable="true" maxChars="9" valueType="numeric"><value>69236<value></customer>

假设您的 XML 字符串位于 $str 中的一些示例代码:

$str = preg_replace('/<customer ([^>]*)>([^<>]*)<\/customer>/i', '<customer $1><value>$2</value></customer>', $str);
$xml = @simplexml_load_string($str);

这将保留属性并将文本值嵌套在子节点中。

This has driven me crazy on several occasions. When SimpleXML encounters a node that only has a text value, it drops all the attributes. My workaround has been to modify the XML prior to parsing with SimpleXML. With a bit of regular expressions, you can create a child node that contains the actual text value. For example, in your situation you can change the XML to:

<customer editable="true" maxChars="9" valueType="numeric"><value>69236<value></customer>

Some example code assuming that your XML string was in $str:

$str = preg_replace('/<customer ([^>]*)>([^<>]*)<\/customer>/i', '<customer $1><value>$2</value></customer>', $str);
$xml = @simplexml_load_string($str);

That would preserve the attributes and nest the text value in a child node.

偏闹i 2024-12-28 22:36:29

我意识到这是一篇旧文章,但以防万一它有用。下面扩展了 @ryanmcdonnell 的解决方案,使其适用于任何标签而不是硬编码标签。希望它能帮助某人。

$str = preg_replace('/<([^ ]+) ([^>]*)>([^<>]*)<\/\\1>/i', '<$1 $2><value>$3</value></$1>', $result);

主要区别在于它将 / 替换为 /<([^ ]+),然后是

告诉它将搜索的该部分与模式中的第一个元素进行匹配。

然后它只是调整占位符 ($1,$2,$3) 以考虑现在有三个子匹配而不是两个的事实。

I realize this is an old post, but in case it proves useful. The below extends @ryanmcdonnell's solution to work on any tags instead of a hard-coded tag. Hopefully it helps someone.

$str = preg_replace('/<([^ ]+) ([^>]*)>([^<>]*)<\/\\1>/i', '<$1 $2><value>$3</value></$1>', $result);

The main different is that it replaces /<customer with /<([^ ]+), and then </customer> with </\\1>

which tells it to match that part of the search against the first element in the pattern.

Then it just adjusts the placeholders ($1,$2,$3) to account for the fact that there are three sub-matches now instead of two.

白鸥掠海 2024-12-28 22:36:29

所以看来这是一个 bug 并在 PHP 7.4.5 中修复。

So it appears that this is a bug and is fixed in PHP 7.4.5.

離人涙 2024-12-28 22:36:29

这是一个老问题,但我发现了一些有用的东西 - 将其解析为 DOMNode 对象。

// $customer contains the SimpleXMLElement
$customerDom = dom_import_simplexml($customer);
var_dump($customerDom->getAttribute('numeric'));

将显示:

string 'numeric'

It's an old question, but I found something that works neat - parse it into a DOMNode object.

// $customer contains the SimpleXMLElement
$customerDom = dom_import_simplexml($customer);
var_dump($customerDom->getAttribute('numeric'));

Will show:

string 'numeric'
回首观望 2024-12-28 22:36:29

下面是一些用于迭代属性并构造 JSON 的代码。如果支持,一个或多个客户。

如果您的 XML 看起来像这样(或只是一个客户),

<xml>
<customer editable="true" maxChars="9" valueType="numeric">69236</customer>
<customer editable="true" maxChars="9" valueType="numeric">12345</customer>
<customer editable="true" maxChars="9" valueType="numeric">67890</customer>
</xml>

请像这样迭代它。

try {
    $xml = simplexml_load_file( "customer.xml" );

    // Find the customer
    $result = $xml->xpath('/xml/customer');

    $bFirstElement = true;
    echo     "var customers  = {\r\n";
    while(list( , $node) = each($result)) {
        if( $bFirstElement ) {
            echo "'". $node."':{\r\n";
            $bFirstElement = false;
        } else {
            echo ",\r\n'". $node."':{\r\n";
        }

        $bFirstAtt = true;
        foreach($node->attributes() as $a => $b) { 
            if( $bFirstAtt ) {
                echo "\t".$a.":'".$b."'";
                $bFirstAtt = false;
            } else {
                echo ",\r\n\t".$a.":'".$b."'";
            }
        }
        echo "}";
    }
    echo "\r\n};\r\n";
} catch( Exception $e ) {
    echo "Exception on line ".$e->getLine()." of file ".$e->getFile()." : ".$e->getMessage()."<br/>";
}

生成这样的 JSON 结构

var customers  = {
'69236':{
    editable:'true',
    maxChars:'9',
    valueType:'numeric'},
'12345':{
    editable:'true',
    maxChars:'9',
    valueType:'numeric'},
'67890':{
    editable:'true',
    maxChars:'9',
    valueType:'numeric'}
};

最后,在您的脚本中,访问这样的属性

WScript.Echo( customers["12345"].editable );

祝你好运

Here's some code to iterate through attributes, and construct JSON. If supports, one or many customers.

If you're XML looks like this (or just one customer)

<xml>
<customer editable="true" maxChars="9" valueType="numeric">69236</customer>
<customer editable="true" maxChars="9" valueType="numeric">12345</customer>
<customer editable="true" maxChars="9" valueType="numeric">67890</customer>
</xml>

Iterate through it like this.

try {
    $xml = simplexml_load_file( "customer.xml" );

    // Find the customer
    $result = $xml->xpath('/xml/customer');

    $bFirstElement = true;
    echo     "var customers  = {\r\n";
    while(list( , $node) = each($result)) {
        if( $bFirstElement ) {
            echo "'". $node."':{\r\n";
            $bFirstElement = false;
        } else {
            echo ",\r\n'". $node."':{\r\n";
        }

        $bFirstAtt = true;
        foreach($node->attributes() as $a => $b) { 
            if( $bFirstAtt ) {
                echo "\t".$a.":'".$b."'";
                $bFirstAtt = false;
            } else {
                echo ",\r\n\t".$a.":'".$b."'";
            }
        }
        echo "}";
    }
    echo "\r\n};\r\n";
} catch( Exception $e ) {
    echo "Exception on line ".$e->getLine()." of file ".$e->getFile()." : ".$e->getMessage()."<br/>";
}

To produce a JSON structure like this

var customers  = {
'69236':{
    editable:'true',
    maxChars:'9',
    valueType:'numeric'},
'12345':{
    editable:'true',
    maxChars:'9',
    valueType:'numeric'},
'67890':{
    editable:'true',
    maxChars:'9',
    valueType:'numeric'}
};

Finally, in your script, access the attribute like this

WScript.Echo( customers["12345"].editable );

Good luck

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文