转换复杂和变量xml

时间:2014-02-08 18:47:00

标签: php xml

我想要在HTML中转换一个复杂的XML。某些标签需要在html标签中替换。

XML就是这样:

<root>
<div>
    <p>
        <em>bol text</em>, some normale text
    </p>
</div>
<list>
    <listitem>
        normal text inside list <em>bold inside list</em>
    </listitem>
    <listitem>
        another text in list...
    </listitem>
</list>
<p>
    A sample paragraph
</p>

元素内的文本是可变的,这意味着我解析的另一个xml可以完全改变。

我想要的输出是这个(对于这种情况):

<root>
    <div>
        <p>
            <strong>bol text</strong>, some normale text
        </p>
    </div>
    <ul>
        <li>
            normal text inside list <strong>bold inside list</strong>
        </li>
        <li>
            another text in list...
        </li>
    </ul>
    <p>
        A sample paragraph
    </p>
</root>

我创建了一个递归函数来解析xml的任何单个节点并将其替换为HTML标记(但不起作用):

$doc = new DOMDocument();
$doc->preserveWhiteSpace = false;
$doc->load('section.xml');
echo $doc->saveHTML();

function printHtml(DOMNode $node)
{
    if ($node->hasChildNodes())
    {
        foreach ($node->childNodes as $child)
        {
            printHtml($child);
        }
    }

    if ($node->nodeName == 'em')
    {
        $newNode = $node->ownerDocument->createElement('strong', $node->nodeValue);
        $node->parentNode->replaceChild($newNode, $node);
    }

    if ($node->nodeName == 'listitem')
    {
        $newNode = $node->ownerDocument->createElement('li', $node->nodeValue);
        $node->parentNode->replaceChild($newNode, $node);
    }
}

任何人都可以帮助我吗? 提前谢谢。

这是一个完整的xml的例子:

<root>
    <div>
        <p>
            <em>bol text</em>, some normale text
        </p>
    </div>
    <list>
        <listitem>
            normal text inside list <em>bold inside list</em>
        </listitem>
        <listitem>
            another text in list...
        </listitem>
    </list>
    <media>
        <info isVisible="false">
            <title>
                <p>Image title <em>in bold</em> not in bold</p>
            </title>
        </info>
        <file isVisible="true">
            <href>
                "path/to/file.jpg"
            </href>
        </file>
    </media>
    <p>
        A sample paragraph
    </p>
</root>

必须转变:

<root>
    <div>
        <p>
            <strong>bol text</strong>, some normale text
        </p>
    </div>
    <ul>
        <li>
            normal text inside list <em>bold inside list</em>
        </li>
        <li>
            another text in list...
        </li>
    </ul>
    <!-- the media tag can be presented in two mode: with title visible, and title hidden -->
    <!-- this is the case when the title is hidden -->
    <img src="path/to/file.jpg" />

    <!-- this is the case when the title is visible -->
    <!-- the info tag (inside media tag) has an attribute isVisible="false" which means it doesn't have to be shown. -->
    <!-- if the info tag has visible=true, the media tag must be transated into
     <div>
        <img src="path/to/file.jpg" />
        <p>Image title <strong>in bold</strong> not in bold</p>
     <div>
     -->
    <p>
        A sample paragraph
    </p>
</root>

2 个答案:

答案 0 :(得分:0)

嗯,也许,这不是最正确的想法,但为什么不只是使用str_replace?这样您就可以清楚地看到要应用的更改列表,并轻松添加/删除新更改。

  1. file_get_contents $file = file_get_contents('file.xml');
  2. str_replace $file = str_replace("<em>", "<strong>", $file);
  3. file_put_contents file_put_contents('file.html', $file);
  4. 更新(关于问题变更的更多想法)

    这里使用PHP + DOM似乎有点棘手(至少对我而言)。也许,使用XSL / XSLT(可扩展样式表语言转换)会更合理。在那种情况下,smth。类似的内容可以在这里找到:How to replace a node-name with another in Xslt?

    XSLT专门用于语言转换 http://en.wikipedia.org/wiki/XSLT

答案 1 :(得分:0)

有一种专门为此任务设计的语言:它称为XSLT,您可以在XSLT中轻松表达所需的转换并从PHP程序中调用它。当然,这是一条学习曲线,但它比编写低级DOM代码要好得多。

在XSLT中,您编写了一组模板规则,说明应如何处理各个元素。示例中的许多元素都是未更改的,因此您可以从执行此操作的默认规则开始:

<xsl:template match="*">
  <xsl:copy><xsl:apply-templates/></xsl:copy>
</xsl:template>

“匹配”部分说明您要匹配的输入部分;规则的主体说明要产生什么输出。 xsl:apply-templates执行递归下降来处理当前元素的子元素。

您可以简单地重命名某些元素,例如

<xsl:template match="listitem">
 <li><xsl:apply-templates/></li>
</xsl:template>

有些规则稍微复杂一些,但仍然很容易表达:

<xsl:tempate match="media/file[@isVisible='true']">
  <img src="{href}"/>
</xsl:template>

我希望您同意这种基于声明规则的方法比您的程序代码更清晰;在六个月的时间内,其他人也更容易改变规则。