1

ある場所からテキスト ノードをコピーし、別の場所にあるテキスト ノードに貼り付けたい XML ファイルがあります。

以下は、操作したいXMLファイルです。

<?xml version="1.0" encoding="UTF-8"?>
<Main>
    <installObj uniqueObjects="2822">
        <object class="Installer" ">
            <visualChildren>
                <object class="InstallSet">
                    <installchildrenMain>
                        <object class="InstallBundle1">
                            <property name="ruleExpression">
                                <string><!***[CDATA[I Need a VALUE!]]***>
                                </string>
                            </property>
                            <property name="bundleName">
                                <string><![CDATA[Australia]]></string>
                            </property>
                            <rules logicalOperation="AND">
                                <object class="CompareVariable">
                                    **
                                    <property name="ruleId">
                                        <string><!***[CDATA[CIAV819]]***>
                                        </string>
                                    </property>
                                    **
                                </object>
                            </rules>
                            <installChildren>
                                <object class="InstallComponent1">
                                    <property name="ruleExpression">
                                        <string><!***[CDATA[CIAV962***]]>
                                        </string>
                                    </property>
                                    <property name="componentName">
                                        <string><![CDATA[AUST]]></string>
                                    </property>
                                    <rules logicalOperation="AND">
                                        <object class="CompareVariable">
                                            <property name="ruleId">
                                                <string><!***[CDATA[CIAV962]***]>
                                                </string>
                                            </property>
                                        </object>
                                    </rules>
                                    <installChildren>
                                        <object class="InstallDirCont">
                                            <property name="ruleExpression">
                                                <string><![***CDATA[CIAV100 || CIAV503]***]>
                                                </string>
                                            </property>
                                            <rules logicalOperation="OR">
                                                <object class="CompareVariable1">
                                                    <property name="ruleId">
                                                        <string><***![CDATA[CIAV100]***]></string>
                                                    </property>
                                                </object>
                                                <object class="CompareVariable2">
                                                    <property name="ruleId">
                                                        <string><***![CDATA[CIAV503]***]></string>
                                                    </property>
                                                </object>
                                            </rules>
                                        </object>
                                    </installChildren>
                                </object>
                                #end of installComponent1
                                <object class="InstallComponent2">
                                    ======
                                    Same as above (Install Component1)
                                    =====
                                </object>
                                #end of installComponent2
                            </installchildren>
                        </object>
                        #installBundle1
                        <object class="InstallBundle2">
                            ====
                            Same structure as InstallBundle1
                            ====
                        </object>
                        #installBundle2
                    </installchildrenMain>
                </object>
                # End of InstallSet
            </visualChildren>
            # end of visualchildren
        </object>
        # end of Installer
    </installObj>
    <restorationObjects count="0" />
</Main>

ここでやりたいことは次のとおりです。

  1. オブジェクト クラス InstallBundle1 - オブジェクト クラス CompareVariable から "CIAV819" テキスト ノード値をコピーし、InstallChildrenMain の直前のオブジェクト クラス InstallBundle1 のテキスト ノードに貼り付けます。

  2. オブジェクト クラス InstallComponent1 - オブジェクト クラス CompareVariable から "CIAV962" テキスト ノード値をコピーし、InstallChildren の直前のオブジェクト クラス InstallComponent1 のテキスト ノードに貼り付けます。

  3. オブジェクト クラス InstallDirCont - オブジェクト クラス CompareVariable1 から "CIAV100" テキスト ノード値をコピーし、オペランド "||" を追加します。また、オブジェクト クラス InstallDirCont - オブジェクト クラス CompareVariable2 から "CIAV503" テキスト ノード値をコピーし、InstallChildren の直前のオブジェクト クラス InstallDirCont のテキスト ノードに貼り付けます。

これは少し面倒に見えますが、この修正が必要です。私はxmlとPHPにまったく慣れていません。助けてくれてありがとう。

また、以下は、この xml ファイルを操作するためにここで使用している PHP コードです。

<?php

$xmldoc = new DOMDocument();
$xmldoc ->load('HR92_latest.iap_xml');


#$x = $xmldoc->getElementsByTagName('/InstallAnywhere_Deployment_Project/installationObjects[1]/object[1]/visualChildren[1]/object[1]/installChildren[1]/object[1]/rules[1]/object[1]/property[8]');
$x = $xmldoc->getElementsByTagName('//property[@name]');


var_dump ($x);
foreach ($x as $string) {
    echo $string->nodeValue, PHP_EOL;
    }
?>

しかし、このコードは o/p を返しています:

object(DOMNodeList)#2 (1) { ["length"]=> int(0) }

基本的に、ここで最初に xpath を見つけ、次にテキスト ノードの値を見つけようとしていますが、失敗しています。どんな助けでも大歓迎です。ありがとう!


2013 年 10 月 17 日 - 更新された質問

@hielsnoppe : DOMDocument の使用に関する制限を見つけています。したがって、xslt コードを使用することを考えました。そして、ほとんど機能しましたが、コマンド プロンプトで実行すると、次のような出力が表示されます。

<object class="InstallComponent1" objectID="03fe9">
            <property><string>CIAV4</string></property>
                <property name="componentName">
                        <string>BA, NT db2</string>
                </property>
                <rules logicalOperation="AND">
                        <object class="CompareVariable" objectID="0304">
                        <property name="ruleId">
                                        <string>CIAV4</string>
                                </property>
                        </object>
                </rules>
                <installChildren>
                        <object class="InstallDirCont" objectID="03005">
                            <property><string>CIAV50 || CIAV60</string></property>
                                <rules logicalOperation="OR">
                                        <object class="CompareVariable">
                                            <property name="ruleId">
                                                <string>CIAV50</string>
                                            </property>
                                        </object>
                                        <object class="CompareVariable">
                                            <property name="ruleId">
                                                <string>CIAV60</string>
                                            </property>
                                        </object>
                                </rules>
                    </object>
                </installChildren>

つまり、出力は次のように表示されます。

<object class="InstallComponent1" objectID="03fe9">
                <property><string>CIAV962</string></property>

それ以外の

<object class="InstallComponent1" objectID="03fe9">
                <property name="ruleExpression"><string><![CDATA[CIAV962]]</string></property>

XMLファイルを開くと、ルール式フィールドが空白のままです!!

私が解決に非常に近いのを助けてください:)ありがとう!!


2013 年 10 月 18 日 - 更新

nodeType == XML_CDATA_SECTION_NODE を追加する必要がありますか? ルール式のテンプレート一致で?

4

1 に答える 1

2

以下では、入力ファイルがそのように見えると仮定しますが、コメントはありません。すべてのソリューションで、必要に応じて XPath セレクターを調整する必要がある場合があります。

<?xml version="1.0" encoding="UTF-8"?>
<Main>
    <installObj uniqueObjects="2822">
        <object class="Installer">
            <visualChildren>
                <object class="InstallSet">
                    <installchildrenMain>
                        <object class="InstallBundle1">
                            <property name="ruleExpression">
                                <string /><!-- PASTE1 -->
                            </property>
                            <property name="bundleName">
                                <string><![CDATA[Australia]]></string>
                            </property>
                            <rules logicalOperation="AND">
                                <object class="CompareVariable">
                                    <property name="ruleId">
                                        <string><![CDATA[CIAV819]]></string><!-- COPY1 -->
                                    </property>
                                </object>
                            </rules>
                            <installChildren>
                                <object class="InstallComponent1">
                                    <property name="ruleExpression">
                                        <string /><!-- PASTE2 -->
                                    </property>    
                                    <property name="componentName">
                                        <string><![CDATA[AUST]]></string>
                                    </property>
                                    <rules logicalOperation="AND">
                                        <object class="CompareVariable">
                                            <property name="ruleId">
                                                <string><![CDATA[CIAV962]]></string><!-- COPY2 -->
                                            </property>
                                        </object>
                                    </rules>
                                    <installChildren>
                                        <object class="InstallDirCont">
                                            <property name="ruleExpression">
                                                <string /><!-- PASTE3 -->
                                            </property>
                                            <rules logicalOperation="OR">
                                                <object class="CompareVariable1">
                                                    <property name="ruleId">
                                                        <string><![CDATA[CIAV100]]></string><!-- COPY3.1 -->
                                                    </property>
                                                </object>
                                                <object class="CompareVariable2">
                                                    <property name="ruleId">
                                                        <string><![CDATA[CIAV503]]></string><!-- COPY3.2 -->
                                                    </property>
                                                </object>
                                            </rules>
                                        </object>
                                    </installChildren>
                                </object><!-- end of installComponent1 -->
                                <object class="InstallComponent2" >
                                    <!--
                                    Same as above (Install Component1)
                                    -->
                                </object><!-- end of installComponent2 -->
                            </installChildren>   
                        </object><!-- end of installBundle1 -->
                        <object class="InstallBundle2" >
                            <!--
                            Same structure as InstallBundle1
                            -->
                        </object><!-- end of installBundle2 -->
                    </installchildrenMain>
                </object><!-- end of InstallSet -->
            </visualChildren><!-- end of visualChildren -->
        </object><!-- end of Installer -->
    </installObj>
    <restorationObjects count="0"/>
</Main>

ロジックを PHP で実行する必要がある場合は、それぞれの PASTE の場所をループして、対応する COPY の場所からデータを取得するDOMXPath代わりに使用してみてください。getElementsByTagName()以下の XSLT ソリューションを好むため、これについては詳しく説明しません。

<?php

$xmldoc = new DOMDocument();
$xmldoc->load('HR92_latest.iap_xml');

$xpath = new DOMXPath($xmldoc);
$paste1 = $xpath->query('//object[starts-with(@class, 'InstallBundle')]/property[@name='ruleExpression']');
$paste2 = $xpath->query('//installChildren/object[starts-with(@class, 'InstallComponent')]/property[@name='ruleExpression']');
$paste3 = $xpath->query('//installChildren/object/installChildren/object[@class='InstallDirCont']/property[@name='ruleExpression']');

foreach ($paste1 as $p) {
    // find corresponding COPY location and pull in the data
}
foreach ($paste2 as $p) {
    // find corresponding COPY location and pull in the data
}
foreach ($paste3 as $p) {
    // find corresponding COPY locations and pull in the data
}

XSLTを使用pick_a_meaningful_name.xsltして、必要な結果を生成するために、上記の例の形式で保存された次の変換を XML ドキュメントに適用することをお勧めします。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output cdata-section-elements="string" />
<xsl:template match="@*|node()">
    <xsl:copy><xsl:apply-templates select="@*|node()" /></xsl:copy>
</xsl:template>
<xsl:template match="//object[starts-with(@class, 'InstallBundle')]/property[@name='ruleExpression']">
    <xsl:copy>
        <xsl:copy-of select="../rules/object/property/string" />
    </xsl:copy>
</xsl:template>
<xsl:template match="//installChildren/object[starts-with(@class, 'InstallComponent')]/property[@name='ruleExpression']">
    <xsl:copy>
        <xsl:copy-of select="../rules/object/property/string" />
    </xsl:copy>
</xsl:template>
<xsl:template match="//installChildren/object/installChildren/object[@class='InstallDirCont']/property[@name='ruleExpression']">
    <xsl:copy>
        <string>
            <xsl:for-each select="../rules[@logicalOperation='OR']/object">
                <xsl:value-of select="./property/string" />
                <xsl:if test="position() &lt; count(../object)"><xsl:value-of select="' || '" /></xsl:if>
            </xsl:for-each>
        </string>
    </xsl:copy>
</xsl:template>
</xsl:transform>

これを行うための PHP コードの最小限の例は、次のXSLTProcessorようになります。

<?php

$xmldoc = new DOMDocument();
$xmldoc->load('HR92_latest.iap_xml');
$xsldoc = new DOMDocument();
$xsldoc->load('pick_a_meaningful_name.xslt');

$xslt = new XSLTProcessor();
$xslt->importStylesheet($xsldoc);
$result = $xslt->transformToDoc($xmldoc);

$result->save('HR92_latest.iap_xml');   // writes result to original file
echo $result->saveXML();                // echoes result
于 2013-10-10T08:46:47.983 に答える