我可能會拋出一個排序上Tagsoup解析器。有些東西可以讀取你的格式,除了這些缺陷外,看起來還不錯。沒有什麼文字會停留在對簡單的基於正則表達式的掃描儀的方式上。我只用你得到的四種節點類型叫我的Tagsoup
:Starttag,Endtag,Text和Comment。對於標籤,您需要了解其標記名和NamespacePrefix。它只是爲了方便而命名爲類似於XML/HTML,但實際上這都是「自己動手」,所以不要將這些術語延伸到任何標準。
改變每個標籤的使用(開始或結束)不具有名稱空間前綴可能看起來像($string
包含了你在你的問題有數據):
$scanner = new TagsoupIterator($string);
$nsPrefix = 'vin';
foreach ($scanner as $node) {
$isTag = $node instanceof TagsoupTag;
$isOfNs = $isTag && $node->getTagNsPrefix() === $nsPrefix;
if ($isTag && !$isOfNs) {
$node = strtr($node, ['&' => '&', '<' => '<']);
}
echo $node;
}
輸出:
<vin:layout name="Page" xmlns:vin="http://www.example.com/vin">
<header>
{someText}
<div>
<!-- some invalid xml code -->
<aas>
<nav class="main">
<vin:show section="Menu" />
</nav>
</div>
</header>
</vin:layout>
的使用來提取裏面的東西一個命名空間的特定標籤可能看起來像:
$scanner = new TagsoupIterator($string);
$parser = new TagsoupForwardNavigator($scanner);
$startTagWithNsPrefix = function ($namespace) {
return function (TagsoupNode $node) use ($namespace) {
/* @var $node TagsoupTag */
return $node->getType() === Tagsoup::NODETYPE_STARTTAG
&& $node->getTagNsPrefix() === $namespace;
};
};
$start = $parser->nextCondition($startTagWithNsPrefix('vin'));
$tag = $start->getTagName();
$parser->next();
echo $html = implode($parser->getUntilEndTag($tag));
輸出:
<header>
{someText}
<div>
<!-- some invalid xml code -->
<aas>
<nav class="main">
<vin:show section="Menu" />
</nav>
</div>
</header>
接着部分是取代$string
的那部分。作爲Tagsoup提供二進制的偏移和長度,這是很容易的(我的快捷方式通過了SimpleXML有點髒):
$xml = substr($string, 0, $start->getEnd()) . substr($string, $parser->getOffset());
$doc = new SimpleXMLElement($xml);
$doc[0] = $html;
echo $doc->asXML();
輸出:
<vin:layout xmlns:vin="http://www.example.com/vin" name="Page">
<header>
{someText}
<div>
<!-- some invalid xml code -->
<aas>
<nav class="main">
<vin:show section="Menu" />
</nav>
</div>
</header>
</vin:layout>
根據具體需要,這需要改變實現。例如,這不允許將相同的標籤放在彼此中。它不會讓你失望,但它並不能解決問題。不知道你是否有這種情況,如果你需要添加一些打開/關閉計數器,導航器類可以很容易地擴展,甚至提供兩種終端標籤查找方法。
這裏給出的例子是使用Tagsoup你可以在這個要點看:https://gist.github.com/4415105
你需要一個解決辦法呢。由於[load_invalid_xml](http://stackoverflow.com/questions/2890120/php-processing-invalid-xml)不起作用,我會嘗試一個SGML工具包,或者SimpleHtmlDom(基於字符串/正則表達式的,而不是的libxml)。作爲快速轉義,使用正則表達式對其進行預處理,以將非命名空間標記轉換爲XML文本,其中包含'= preg_replace(「#<((?!/?w +:\ w +)。*?)>#smix」,「< $ 1 >「,$ xml)'。 (這是一個評論,以避免甚至提到它典型的SO flak。) – mario
爲什麼你想解析這個,你想要做什麼? – GreenRover
這是一些tempalte文件。所有名稱空間標籤都代表函數調用。所以我需要用一些其他內容(文本或更多名稱空間標籤)替換名稱空間標籤。但我認爲唯一的辦法就是使用正則表達式... – dkoch