在XML文件中组合两个元素

时间:2018-02-28 03:05:18

标签: php xml

首先感谢您的帮助!

我有一个看起来像这样的xml:

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE tv SYSTEM "xmltv.dtd">

<tv source-info-url="http://tvschedule.zap2it.com/" source-info-name="zap2it.com" generator-info-name="zap2xml" generator-info-url="zap2xml@gmail.com">
<channel id="I16689330.labs.zap2it.com">
    <display-name>502 WCBSDT</display-name>
    <display-name>502</display-name>
    <display-name>WCBSDT</display-name>
    <icon src="https://zap2it.tmsimg.com/h3/NowShowing/16689/s28711_h3_aa.png" />
</channel>
<programme start="20180303203000 -0500" stop="20180303230000 -0500" channel="I20453335.labs.zap2it.com">
    <title lang="en">NBA Basketball</title>
    <sub-title lang="en">Boston Celtics at Houston Rockets</sub-title>
    <desc lang="en">From the Toyota Center in Houston.</desc>
    <category lang="en">Sports</category>
    <category lang="en">Basketball</category>
    <length units="minutes">120</length>
    <icon src="https://zap2it.tmsimg.com/assets/p14464724_tb2_v5_aa.jpg" />
    <url>https://tvlistings.zap2it.com//overview.html?programSeriesId=SP00371600&amp;tmsId=SP003716000000</url>
    <episode-num system="dd_progid">SP00371600.0000</episode-num>
    <new />
    <subtitles type="teletext" />
</programme>
</tv>

我想生成这样的东西,将标题与子标题结合起来:

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE tv SYSTEM "xmltv.dtd">

<tv source-info-url="http://tvschedule.zap2it.com/" source-info-name="zap2it.com" generator-info-name="zap2xml" generator-info-url="zap2xml@gmail.com">
<channel id="I16689330.labs.zap2it.com">
    <display-name>502 WCBSDT</display-name>
    <display-name>502</display-name>
    <display-name>WCBSDT</display-name>
    <icon src="https://zap2it.tmsimg.com/h3/NowShowing/16689/s28711_h3_aa.png" />
</channel>
<programme start="20180303203000 -0500" stop="20180303230000 -0500" channel="I20453335.labs.zap2it.com">
    <title lang="en">NBA Basketball: Boston Celtics at Houston Rockets</title>
    <desc lang="en">From the Toyota Center in Houston.</desc>
    <category lang="en">Sports</category>
    <category lang="en">Basketball</category>
    <length units="minutes">120</length>
    <icon src="https://zap2it.tmsimg.com/assets/p14464724_tb2_v5_aa.jpg" />
    <url>https://tvlistings.zap2it.com//overview.html?programSeriesId=SP00371600&amp;tmsId=SP003716000000</url>
    <episode-num system="dd_progid">SP00371600.0000</episode-num>
    <new />
    <subtitles type="teletext" />
</programme>
</tv>

如果可以使用更好的PHP脚本来完成

2 个答案:

答案 0 :(得分:1)

因此,如果我们在public class MyCache { final ConcurrentHashMap<Integer, Boolean> cache = new ConcurrentHashMap<>(); //it's a ConcurrentHashMap to be able to use putIfAbsent public boolean contains(Integer num) { return cache.contains(num); } public void add(Integer nums) { cache.putIfAbsent(num, true); } public clear(){ cache.clear(); } public remove(Integer num) { cache.remove(num); } } 中有XML字符串,我们可以使用$string将其解析为XML对象:

simplexml_load_string

然后将元素作为对象属性访问:

$xml = simplexml_load_string($string);

要构建所需的组合属性,它就像直观一样(注意必须如何处理短划线特殊字符):

> echo $xml->title;
NBA Basketball

因为我们已将子标题属性合并到标题中,所以我们不再需要它:

$xml->title .= ': '.$xml->{'sub-title'};

然后打印整个对象:

unset($xml->{'sub-title'});

示例完整执行:

> echo $xml->asXML();
<?xml version="1.0"?>
<programme start="20180303203000 -0500" stop="20180303230000 -0500" channel="I20453335.labs.zap2it.com">
    <title lang="en">NBA Basketball: Boston Celtics at Houston Rockets</title>

    <desc lang="en">From the Toyota Center in Houston.</desc>
    <category lang="en">Sports</category>
    <category lang="en">Basketball</category>
    <length units="minutes">120</length>
    <icon src="https://zap2it.tmsimg.com/assets/p14464724_tb2_v5_aa.jpg"/>
    <url>https://tvlistings.zap2it.com//overview.html?programSeriesId=SP00371600&amp;tmsId=SP003716000000</url>
    <episode-num system="dd_progid">SP00371600.0000</episode-num>
    <new/>
    <subtitles type="teletext"/>
</programme>

答案 1 :(得分:0)

或者,考虑XSLT,这是用于转换XML文件的专用语言。 PHP可以使用其php-xsl类运行XSLT 1.0(确保它在.ini文件中启用)。此外,XSLT是可移植的,不需要PHP来运行它。大多数其他语言(Java,Python,Perl,VB)可以运行这样的脚本,甚至可以运行独立的XSLT processors

具体来说,在XSLT脚本下运行Identity Transform以按原样复制文档,然后使用 title subtitle的concat()重写程序节点,最后再现所有其他节点和属性。虽然这可能看起来有些过分,但如果您的XML更大并且维护了许多程序节点,那么这个XSLT将合并所有标题子标题而不会循环。

XSLT (另存为.xsl文件,一个特殊的.xml文件)

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" omit-xml-declaration="yes" indent="yes"/>
    <xsl:strip-space elements="*"/>

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

    <!-- REWRITE PROGRAMME -->
    <xsl:template match="programme"> 
        <xsl:copy>     
            <xsl:copy-of select="@*"/>
            <title><xsl:value-of select="concat(title, ' ', sub-title)" /></title>
            <xsl:apply-templates select="*[name()!='title' and name()!='sub-title']" /> 
        </xsl:copy>       
    </xsl:template>

</xsl:stylesheet>

<强> PHP

$xml = new DOMDocument;
$xml->load('Input.xml');

$xsl = new DOMDocument;
$xsl->load('XSLT_Script.xsl');

// Configure transformer
$proc = new XSLTProcessor;
$proc->importStyleSheet($xsl);

// Transform XML source
$newXML = new DOMDocument;
$newXML = $proc->transformToXML($xml);

// Output to console
echo $newXML;

// Output to file
file_put_contents('Output.xml', $newXML);

<强>输出

<programme start="20180303203000 -0500" stop="20180303230000 -0500" channel="I20453335.labs.zap2it.com">
  <title>NBA Basketball Boston Celtics at Houston Rockets</title>
  <desc lang="en">From the Toyota Center in Houston.</desc>
  <category lang="en">Sports</category>
  <category lang="en">Basketball</category>
  <length units="minutes">120</length>
  <icon src="https://zap2it.tmsimg.com/assets/p14464724_tb2_v5_aa.jpg"/>
  <url>https://tvlistings.zap2it.com//overview.html?programSeriesId=SP00371600&amp;tmsId=SP003716000000</url>
  <episode-num system="dd_progid">SP00371600.0000</episode-num>
  <new/>
  <subtitles type="teletext"/>
</programme>