如何将带有名称空间的标签更改为默认名称空间中带有前缀的标签

时间:2018-06-22 13:17:43

标签: php regex xml

我需要通过用下划线替换命名空间冒号来修改一些XML标记,这样:

<video:rating>5</video:rating>
<video:view_count>128</video:view_count>
<video:publication_date>2017-02-25T00:25:44+00:00</video:publication_date>

将成为这个:

<video_rating>5</video_rating>
<video_view_count>128</video_view_count>
<video_publication_date>2017-02-25T00:25:44+00:00</video_publication_date>

请注意,日期中的冒号没有更改。我正在尝试创建一个可捕获“ <”和“>”之间任何冒号的正则表达式,然后将其替换为“ _”,但是我是一个正则表达式菜鸟,因此证明它是不可能的:^)

2 个答案:

答案 0 :(得分:1)

如果要避免意外的结果,最好在处理XML时始终使用为XML设计的工具。

假设您有一个这样的站点地图文件:

<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
        xmlns:video="http://www.google.com/schemas/sitemap-video/1.1">
  <url>
     <loc>http://example.com/video-page.html</loc>
     <video:video>            
        <video:thumbnail_loc>http://example.com/thumb1.jpg</video:thumbnail_loc>
        <video:title>Clown in the garden</video:title>
        <video:description>Crazy clown is riding a rabbit.</video:description>    
        <video:content_loc>http://www.example.com/video1.mp4</video:content_loc>
     </video:video>
  </url>
</urlset>

要将具有名称空间“ video”的元素更改为默认名称空间中具有“ video_”开头的本地名称的元素,可以使用XSLT(可扩展样式表语言转换)定义模板,在其中可以编辑xml的元素文献。这些样式表使用xpath语言精确定位所需的元素。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
        xmlns:video="http://www.google.com/schemas/sitemap-video/1.1">
    <xsl:output indent="yes" encoding="UTF-8"/>

    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="video:*">
        <xsl:element name="{concat('video_', local-name(.))}">
            <xsl:copy-of select="@*"/>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:element>
    </xsl:template>
</xsl:stylesheet>

请注意,您需要两个模板:第一个(通常称为 identity 模板)复制所有文档,第二个仅处理“视频”命名空间中的标记。

那么您在PHP代码中要做的就是将XSLT应用于XML文档:

$xmldoc = new DOMDocument;
$xmldoc->load($sitemapFile);

$xsldoc = new DOMDocument;
$xsldoc->load($stylesheetFile);

$xsl = new XSLTProcessor();
$xsl->importStyleSheet($xsldoc);
echo $xsl->transformToXML($xmldoc);

答案 1 :(得分:-3)

这是一个PHP示例片段。

正则表达式仅使用标记内的冒号,以下划线代替。

<?php

$str = '<video:rating>5</video:rating>
<video:view_count>128</video:view_count>
<video:publication_date>2017-02-25T00:25:44+00:00</video:publication_date>';

$result = preg_replace('@</?\w+\K:(?=\w+>)@m', '_', $str);

echo '<br/><br/><strong>BEFORE</strong><br/>';
echo htmlentities($str);
echo '<br/><br/><strong>AFTER</strong><br/><br/>';
echo htmlentities($result);

您可以测试正则表达式here on regex101