Как я могу добавить XML с пространствами имен в другой XML в PHP, DOMDocument? - PullRequest
1 голос
/ 24 июня 2019

Я пытаюсь сгенерировать XML с частями XML на PHP, используя DOMDocument, и мне нужно добавить две части XML.

У меня есть две части XML с пространством имен. Один для «конверта» с данными, а другой для зацикленных данных, и мне нужно собрать их вместе. Поместите зацикленные данные в конверт.

Я уже пробовал много примеров из StackOverflow, но они не упоминают, как делать с пространствами имен.

Давайте посмотрим на несколько примеров:

1-я часть:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" 
    xmlns:aut="http://www.domain.xy/OSB/Authentication/" 
    xmlns:sch="http://www.domain.xy/schedule/ScheduleManager/" 
    xmlns:urn="urn:entsoe.eu:edi:ess:schedulemessage:3:3">
    <soapenv:Header>
        <aut:mekAuth>
            <username>username</username>
            <password>p455w0rd</password>
        </aut:mekAuth>
    </soapenv:Header>
    <soapenv:Body>
        <sch:receiveScheduleRequest>
            <urn:ScheduleMessage DtdVersion="3" DtdRelease="3">
                <urn:MessageIdentification v="xyz"/>
                <urn:MessageVersion v="34"/>
                <urn:MessageType v="xyz"/>
                <urn:ProcessType v="xyz"/>
                <urn:ScheduleClassificationType v="xyz"/>
                <urn:SenderIdentification v="xyz" codingScheme="xyz"/>
                <urn:SenderRole v="xyz"/>
                <urn:ReceiverIdentification v="xyz" codingScheme="xyz"/>
                <urn:ReceiverRole v="xyz"/>
                <urn:MessageDateTime v="2019-06-23T23:23:28Z"/>
                <urn:ScheduleTimeInterval v="2019-06-22T22:00Z/2019-06-23T22:00Z"/>


                /* PART 2 WILL GOES HERE */


            </urn:ScheduleMessage>
        </sch:receiveScheduleRequest>
    </soapenv:Body>
</soapenv:Envelope>

2-я часть:


                <urn:ScheduleTimeSeries>
                    <urn:SendersTimeSeriesIdentification v="xyz"/>
                    <urn:SendersTimeSeriesVersion v="34"/>
                    <urn:BusinessType v="xyz"/>
                    <urn:Product v="xyz"/>
                    <urn:ObjectAggregation v="xyz"/>
                    <urn:InArea v="xyz" codingScheme="xyz"/>
                    <urn:MeteringPointIdentification v="xyz codingScheme="xyz"/>
                    <urn:InParty v="xyz" codingScheme="xyz"/>
                    <urn:MeasurementUnit v="KWT"/>

                    /* PART 3 WILL GOES HERE */

                </urn:ScheduleTimeSeries>

3-я часть:

                    <urn:Period>
                        <urn:TimeInterval v="2019-06-22T22:00Z/2019-06-23T22:00Z"/>
                        <urn:Resolution v="PT15M"/>
                        <urn:Interval  >
                            <urn:Pos v="1"/>
                            <urn:Qty v="0"/>
                        </urn:Interval>
                        <urn:Interval  >
                            <urn:Pos v="2"/>
                            <urn:Qty v="0"/>
                        </urn:Interval>
                        <urn:Interval  >
                            <urn:Pos v="3"/>
                            <urn:Qty v="0"/>
                        </urn:Interval>
                        <urn:Interval  >
                            <urn:Pos v="4"/>
                            <urn:Qty v="0"/>
                        </urn:Interval>
                    </urn:Period>

и мне нужно сделать это:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" 
    xmlns:aut="http://www.domain.xy/OSB/Authentication/" 
    xmlns:sch="http://www.domain.xy/schedule/ScheduleManager/" 
    xmlns:urn="urn:entsoe.eu:edi:ess:schedulemessage:3:3">
    <soapenv:Header>
        <aut:mekAuth>
            <username>username</username>
            <password>p455w0rd</password>
        </aut:mekAuth>
    </soapenv:Header>
    <soapenv:Body>
        <sch:receiveScheduleRequest>
            <urn:ScheduleMessage DtdVersion="3" DtdRelease="3">
                <urn:MessageIdentification v="xyz"/>
                <urn:MessageVersion v="34"/>
                <urn:MessageType v="xyz"/>
                <urn:ProcessType v="xyz"/>
                <urn:ScheduleClassificationType v="xyz"/>
                <urn:SenderIdentification v="xyz" codingScheme="xyz"/>
                <urn:SenderRole v="xyz"/>
                <urn:ReceiverIdentification v="xyz" codingScheme="xyz"/>
                <urn:ReceiverRole v="xyz"/>
                <urn:MessageDateTime v="2019-06-23T23:23:28Z"/>
                <urn:ScheduleTimeInterval v="2019-06-22T22:00Z/2019-06-23T22:00Z"/>


                <urn:ScheduleTimeSeries>
                    <urn:SendersTimeSeriesIdentification v="xyz"/>
                    <urn:SendersTimeSeriesVersion v="34"/>
                    <urn:BusinessType v="xyz"/>
                    <urn:Product v="xyz"/>
                    <urn:ObjectAggregation v="xyz"/>
                    <urn:InArea v="xyz" codingScheme="xyz"/>
                    <urn:MeteringPointIdentification v="xyz" codingScheme="xyz"/>
                    <urn:InParty v="xyz" codingScheme="xyz"/>
                    <urn:MeasurementUnit v="KWT"/>

                     <urn:Period>
                        <urn:TimeInterval v="2019-06-22T22:00Z/2019-06-23T22:00Z"/>
                        <urn:Resolution v="PT15M"/>
                        <urn:Interval  >
                            <urn:Pos v="1"/>
                            <urn:Qty v="0"/>
                        </urn:Interval>
                        <urn:Interval  >
                            <urn:Pos v="2"/>
                            <urn:Qty v="0"/>
                        </urn:Interval>
                        <urn:Interval  >
                            <urn:Pos v="3"/>
                            <urn:Qty v="0"/>
                        </urn:Interval>
                        <urn:Interval  >
                            <urn:Pos v="4"/>
                            <urn:Qty v="0"/>
                        </urn:Interval>                 
                     </urn:Period>

                </urn:ScheduleTimeSeries>


            </urn:ScheduleMessage>
        </sch:receiveScheduleRequest>
    </soapenv:Body>
</soapenv:Envelope>

Я делаю такие позиции:

    public function generate_positions( $data, $res = "daily" )
    {
            $dom = new DOMDocument('1.0', 'UTF-8');
            $dom->xmlStandalone = true;
            $dom->formatOutput = true;

            $period = $dom->createElement("urn:Period");
            $period = $dom->appendChild( $period );

            $timeInterval = $dom->createElement("urn:TimeInterval");
            // $timeInterval->setAttribute("v", $data->interval);
            $timeInterval = $period->appendChild( $timeInterval );

            $resolution = $dom->createElement("urn:Resolution");
            $resolution->setAttribute("v", $time_resolution[$res]);
            $resolution = $period->appendChild( $resolution );

            foreach ( $data as $key => $value )
            {
                $interval = $dom->createElement("urn:Interval");
                $interval = $period->appendChild( $interval );

                $pos = $dom->createElement("urn:Pos");
                $pos->setAttribute("v", $value["pos"]);
                $pos = $interval->appendChild($pos);

                $qty = $dom->createElement("urn:Qty");
                $qty->setAttribute("v", $value["value"]);
                $qty = $interval->appendChild($qty);
            }

            return $dom->saveXML( $period );
    }

Я бы хотел написать функцию генерации 2-й части, такую ​​как generate_positions () , но я не знаю, как "вставить" возвращенный xml из generate_positions

Я пытался с appendXML ($ inner_xml), но обычно получал следующее сообщение об ошибке:

Сообщение: DOMDocumentFragment :: appendXML (): ошибка пространства имен: Урна префикса пространства имен для периода не определена

У меня есть объявления пространства имен, но я не знаю, где их использовать в этом случае

1 Ответ

1 голос
/ 24 июня 2019

Прежде всего, вам нужно правильно сгенерировать фрагменты XML и избежать ошибки:

Ошибка пространства имен: Префикс пространства имен для урны на Период не определен

Комуиспользовать префиксы пространства имен, используя createElementNS() вместо createElement():

$urn_uri = "urn:entsoe.eu:edi:ess:schedulemessage:3:3";

$period = $dom->createElementNS(urn_uri, "urn:Period");
$timeInterval = $dom->createElementNS(urn_uri, "urn:TimeInterval");
$resolution = $dom->createElementNS(urn_uri, "urn:Resolution");

...

Как только каждый фрагмент будет сгенерирован правильно, рассмотрим XSLT , язык специального назначенияпреобразовывать XML-файлы, поскольку он поддерживает функцию document() для анализа внешних XML-файлов.PHP может запускать сценарии XSLT 1.0, используя свою библиотеку php / xsl (может потребоваться включение расширения).

Ниже предполагается, что пространства имен правильно определены в корне 2-го и 3-го фрагментов. ПРИМЕЧАНИЕ : это решение XSLT не будет работать, если фрагменты не будут правильно сформированы.

XSLT (сохранить как файл .xsl, специальный файл .xml)

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                              xmlns:aut="http://www.domain.xy/OSB/Authentication/" 
                              xmlns:sch="http://www.domain.xy/schedule/ScheduleManager/" 
                              xmlns:urn="urn:entsoe.eu:edi:ess:schedulemessage:3:3">
  <xsl:output indent="yes"/>
  <xsl:strip-space elements="*"/>

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

  <xsl:template match="urn:ScheduleMessage">
    <xsl:copy>
      <xsl:apply-templates select="*"/>
      <xsl:apply-templates select="document('2nd Part.xml')/urn:ScheduleTimeSeries"/>     
    </xsl:copy>
  </xsl:template>

  <xsl:template match="urn:ScheduleTimeSeries">
    <xsl:copy>
      <xsl:apply-templates select="*"/>
      <xsl:copy-of select="document('3rd Part.xml')/*"/>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

PHP (выполнить преобразование только в первой части)

// LOAD XML AND XSLT
$xml = new DOMDocument('1.0', 'UTF-8');
$xml->load('1st Part.xml');

$xsl = new DOMDocument('1.0', 'UTF-8');   
$xsl->load('Script.xsl');

// INITIALIZE TRANSFORMER
$proc = new XSLTProcessor;
$proc->importStyleSheet($xsl);

// RUN TRANSFORMATION
$newXML = $proc->transformToDoc($xml);

// ECHO TO CONSOLE
echo $newXML;

// SAVE TO FILE
file_put_contents('Output.xml', $newXML);

Выход

<?xml version="1.0" encoding="utf-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:aut="http://www.domain.xy/OSB/Authentication/" xmlns:sch="http://www.domain.xy/schedule/ScheduleManager/" xmlns:urn="urn:entsoe.eu:edi:ess:schedulemessage:3:3">
  <soapenv:Header>
    <aut:mekAuth>
      <username>username</username>
      <password>p455w0rd</password>
    </aut:mekAuth>
  </soapenv:Header>
  <soapenv:Body>
    <sch:receiveScheduleRequest>
      <urn:ScheduleMessage>
        <urn:MessageIdentification v="xyz" />
        <urn:MessageVersion v="34" />
        <urn:MessageType v="xyz" />
        <urn:ProcessType v="xyz" />
        <urn:ScheduleClassificationType v="xyz" />
        <urn:SenderIdentification v="xyz" codingScheme="xyz" />
        <urn:SenderRole v="xyz" />
        <urn:ReceiverIdentification v="xyz" codingScheme="xyz" />
        <urn:ReceiverRole v="xyz" />
        <urn:MessageDateTime v="2019-06-23T23:23:28Z" />
        <urn:ScheduleTimeInterval v="2019-06-22T22:00Z/2019-06-23T22:00Z" />
        <urn:ScheduleTimeSeries>
          <urn:SendersTimeSeriesIdentification v="xyz" />
          <urn:SendersTimeSeriesVersion v="34" />
          <urn:BusinessType v="xyz" />
          <urn:Product v="xyz" />
          <urn:ObjectAggregation v="xyz" />
          <urn:InArea v="xyz" codingScheme="xyz" />
          <urn:MeteringPointIdentification v="xyz" codingScheme="xyz" />
          <urn:InParty v="xyz" codingScheme="xyz" />
          <urn:MeasurementUnit v="KWT" />
          <urn:Period>
            <urn:TimeInterval v="2019-06-22T22:00Z/2019-06-23T22:00Z" />
            <urn:Resolution v="PT15M" />
            <urn:Interval>
              <urn:Pos v="1" />
              <urn:Qty v="0" />
            </urn:Interval>
            <urn:Interval>
              <urn:Pos v="2" />
              <urn:Qty v="0" />
            </urn:Interval>
            <urn:Interval>
              <urn:Pos v="3" />
              <urn:Qty v="0" />
            </urn:Interval>
            <urn:Interval>
              <urn:Pos v="4" />
              <urn:Qty v="0" />
            </urn:Interval>
          </urn:Period>
        </urn:ScheduleTimeSeries>
      </urn:ScheduleMessage>
    </sch:receiveScheduleRequest>
  </soapenv:Body>
</soapenv:Envelope>
...