可以在PHP中将格式化的字符串转换为xml格式或数组吗?我有这样的字符串格式:
$prop = "
large {
width: 10px;
height: 10px;
}
small {
width: 5px;
height: 5px;
}
";
我希望将此字符串转换为xml格式或数组,如:
<large>
<width>10px</width>
<height>10px</height>
</large>
<small>
<width>5px</width>
<height>5px</height>
</small>
$array = array(
"large" => array(
"width" => "10px",
"height" => "10px"
),
"small" => array(
"width" => "5px",
"height" => "5px"
)
);
感谢。
答案 0 :(得分:4)
因为你的输入数据格式很好,你可以创建一个非常简单的递归后代解析器 - 即使没有那么多的递归。或者只是一个简单的堆栈:
$props = array_filter(array_map('trim', explode("\n", $prop)));
$stack = [$node = $xml = new SimpleXMLElement('<root/>')];
foreach ($props as $str)
{
if ($str === '}') {
array_pop($stack);
$node = end($stack);
continue;
}
if (preg_match('~^(\w+) {$~', $str, $matches)) {
$node = $stack[] = $node->addChild($matches[1]);
continue;
}
if (preg_match('~^(\w+):\s*(.*)$~', $str, $matches)) {
$node->addChild($matches[1], htmlspecialchars($matches[2]));
continue;
}
throw new UnexpectedValueException(sprintf('Unable to parse: "%s"', $str));
}
$xml->asXML('php://output');
第二个例子(先前缺失的)的输出然后是(美化):
<?xml version="1.0"?>
<root>
<button>
<large>
<bond>
<width>10px;</width>
<height>10px;</height>
</bond>
<style>
<background>
<color>#ffffff;</color>
<image>url(www.px.com/aui.png) -10px;</image>
<another>
<width>100px;</width>
<height>100px;</height>
</another>
</background>
</style>
</large>
<small>
<bond>
<width>10px;</width>
<height>10px;</height>
</bond>
<style>
<color>#fff;</color>
<border>1px solid #000;</border>
</style>
</small>
</button>
</root>
我建议你在这里使用XML,因为它可以比不能有重复键的数组更好地表示结构。
也可以使用递归函数调用而不是堆栈。但这需要将输入流包装在无倒带迭代器中以不中断(或使用array_shift
但我不喜欢那样):
$parse = function($p, SimpleXMLElement $t) use (&$parse) {
foreach($p as $s) {
if ($s === '}') {
break;
}
if (preg_match('~^([^ ]+) {$~', $s, $m)) {
$p->next();
$parse($p, $t->addChild($m[1]));
continue;
}
if (preg_match('~^([^:]+):\s*(.*)$~', $s, $m)) {
$n = $t->addChild($m[1], htmlspecialchars($m[2]));
continue;
}
}
};
$props = array_filter(array_map('trim', explode("\n", $prop)));
$xml = new SimpleXMLElement('<root/>');
$parse(new NoRewindIterator(new ArrayIterator($props)), $xml);
$xml->asXML('php://output');
答案 1 :(得分:1)
有效的解决方案: - )
$prop = "
large {
width: 10px;
height: 10px;
color: red;
}
small {
width: 5px;
height: 5px;
}
medium {
width: 5px;
height: 5px;
}
";
//remove carriage return
$prop = str_replace(array('.', ' ', "\n", "\t", "\r"), '', $prop);
//get into main names and values
preg_match_all('/([^\{]+)\{([^\}]+)\}/i',$prop,$matches);
$arr_names = $matches[1];
$arr_values = $matches[2];
$arr_result = array();
foreach($arr_names as $i=>$name){
$value = $arr_values[$i];
//get into main sub names and values
preg_match_all('/([^\:]+)\:([^\;]+)\;/i',$value,$m);
$arr_n = $m[1];
$arr_v = $m[2];
$arr = array();
foreach($arr_n as $j=>$n){
$v = $arr_v[$j];
$arr[$n] = $v;
}
$arr_result[$name] = $arr;
}
print_r($arr_result);
答案 2 :(得分:0)
这应该有效
$elements = explode('}', trim($prop));
for($i = 0 ; $i < sizeof($elements); $i++) {
list($name, $styles) = explode('{', $elements[$i]);
$name = trim($name);
if(empty($name)) {
continue;
}
$rules = explode(';', $styles);
for($j=0; $j < sizeof($rules); $j++) {
list($ruleName, $ruleVal) = explode(':', $rules[$j]);
$ruleName = trim($ruleName);
if(empty($ruleName)) {
continue;
}
$result[$name][$ruleName] = trim($ruleVal);
}
}
echo '<pre>';
var_dump($result);
echo '</pre>';
答案 3 :(得分:-1)
我的解决方案:
我尝试使用preg_replace()
和eval()
并使用多维格式。也许你可以改进我的preg_replace
模式。
$string = "
button {
large {
bond {
width: 10px;
height: 10px;
}
style {
background {
color: #ffffff;
image: url(www.px.com/aui.png) -10px;
another {
width: 100px;
height: 100px;
}
}
}
}
small {
bond {
width: 10px;
height: 10px;
}
style {
color: #fff;
border: 1px solid #000;
}
}
}
";
$string = preg_replace("/(\s+\:)/", ':', $string);
$string = preg_replace("/(\:\s+)/", ':', $string);
$string = preg_replace("/(\s+\{)/", '{', $string);
$string = preg_replace("/([\w\d_]+)\:(.*?)\;/", '"$1" => "$2",', $string);
$string = preg_replace("/([\w\d_]+)\{/", '"$1" => array (', $string);
$string = preg_replace("/\}/", ')', $string);
$string = preg_replace("/\"\,(\s+)\)/", '"$1)', $string);
$string = preg_replace("/\)(\s+)\"/", '),$1"', $string);
$arr = eval('return array('.$string.');');
print_r($arr);
感谢。