如何使用包含标签的文本表示形式的跨度替换自定义标签

时间:2019-01-25 15:54:56

标签: javascript php

我正在尝试以HTML形式直观地表示xml代码。

一个简单的例子是这样:

原始来源:

<g id="1">some content</g> other content <s/>

所需的输出:

<span data-id="1">&lt;g id=&quot;1&quot;&gt;</span>some content<span data-closingof="1">&lt;/g&gt;</span> other content <span>&lt;s/&gt;</span>

我对正则表达式进行了很多尝试,但都取得了不错的效果,但是如果嵌套了元素,它会失败。

还有其他方法吗? (例如,一些允许此类转换的XML解析器)

谢谢。

3 个答案:

答案 0 :(得分:0)

我不建议使用正则表达式进行XML处理,但这可能更合适。

$input = '<g id="1">some content</g> other content <s/>';
echo preg_replace_callback("/(<.*?>)/", function($tag) {
        return "<span>".htmlentities($tag[1])."</span>";
    },
    $input);

这将在<>中查找任何内容并对其进行编码-同时将其包含在<span>标签中。

输出...

<span>&lt;g id=&quot;1&quot;&gt;</span>some content<span>&lt;/g&gt;</span> other content <span>&lt;s/&gt;</span>

由于这只是一个有限的示例,因此可能并不适合所有尺寸,但值得一试。

更新

通过添加数据ID的更新,我已经更新了代码,它保留了标记级别的堆栈,并在找到匹配的结束标记时添加了标记(尽管它不检查标记的类型) ,它将忽略和自关闭标签,因为这些标签没有其他内容。

$input = '<g id="1">some <g>2</g>content</g> other content <s/>';
$tagID = [];
echo preg_replace_callback("/(<.*?>)/", function($tag) use (&$tagID) {
    if ( substr($tag[1], -2) == "/>" ) {
        $out = "<span>".htmlentities($tag[1])."</span>";
    }
    else {
        $add = "";
        if ( substr($tag[1],0,2) == "</" )    {
            $id = array_pop($tagID);
            if ( !empty($id) )  {
                $add = ' data-closingof="'.$id.'"';
            }
        }
        else    {
            if (preg_match('/id="(.*?)"/', $tag[1], $match)) {
                $id = $match[1];
                $add = ' data-id="'.$id.'"';
            }
            else {
                $id = "";
            }
            array_push($tagID, $id);
        }
        $out = "<span{$add}>".htmlentities($tag[1])."</span>";
    }
    return $out;
},
$input);

答案 1 :(得分:0)

我最终得到了这样的东西。

class TagsConverter {
    private $parser;

    private $nestedIDs = [];
    private $output = '';

    function __construct() {
        $this->parser = xml_parser_create();
        xml_set_object($this->parser, $this);
        xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, false);
        xml_set_element_handler($this->parser, "tagOpen", "tagClose");
        xml_set_character_data_handler($this->parser, "tagData");
    }

    function __destruct() {
        xml_parser_free($this->parser);
        unset($this->parser);
    }

    function reset() {
        $this->output = '';
        $this->nestedAttribs = [];
    }

    function transform($xml) {
        $xml = '<root>' . $xml . '</root>';
        xml_parse($this->parser, $xml, true);

        $finalOutput = $this->output;

        $this->reset();

        return $finalOutput;
    }

    function tagOpen($parser, $tag, $attributes) {
        if (isset($attributes["id"]))
            $this->nestedIDs[] = $attributes["id"];

        switch($tag) {
            case "bx":
                $this->output .= '<span>' . htmlentities('<bx />') . "</span>";
                break;
            case "g":
                $id = $attributes["id"];
                $this->output .= '<span data-id="' . $id .'">' . htmlentities('<g id="'.$id.'">') . "</span>";
                break;
            default:
                break;
        }
    }

    function tagData($parser, $cdata) {
        $this->output .= $cdata;
    }

    function tagClose($parser, $tag) {
        switch($tag) {
            case "g":
                $id = array_pop($this->nestedIDs);
                $this->output .= '<span data-closingof="' . $id .'">' . htmlentities('</g>') . "</span>";
                break;
            default:
                break;
        }
    }
}

示例运行:

$p = new TagsConverter();
echo $p->transform('<g id="1">test g <g id="2">222</g></g> <g id="3">3333</g> other <x/> content <g id="4">444</g> <bx/>');

<span data-id="1">&lt;g id=&quot;1&quot;&gt;</span>test g <span data-id="2">&lt;g id=&quot;2&quot;&gt;</span>222<span data-closingof="2">&lt;/g&gt;</span><span data-closingof="1">&lt;/g&gt;</span> <span data-id="3">&lt;g id=&quot;3&quot;&gt;</span>3333<span data-closingof="3">&lt;/g&gt;</span> other  content <span data-id="4">&lt;g id=&quot;4&quot;&gt;</span>444<span data-closingof="4">&lt;/g&gt;</span> <span>&lt;bx /&gt;</span>

我想知道JS是否有办法。

答案 2 :(得分:-1)

您可以使用它,但是我不知道您的xml文件是什么样子,所以我无法为您提供示例代码。

这将使xml成为数组,因此您可以轻松地将其取出

    $getXml = file_get_contents('xml.xml');
    $xml = simplexml_load_string($getXml) or die("Error: Cannot create object");

这将遍历数组

    foreach($xml->channel->item as $item) {
        //here you could do something like this
        echo "<h1>";
        print_r($item->title);
        echo "</h1>";
        echo "<br>";
        }

您也可以执行此操作,这将打印xml中的所有元素

     print_r($xml);

有关simplexml_load_string的文档: https://www.w3schools.com/php/func_simplexml_load_string.asp

如果您不了解plz评论