0

attribute=ruleId を持つ要素からテキスト ノード値 (例: CIAV819) をコピーし、attribute=ruleExpression を持つ次のノード要素に貼り付けたい 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[]]></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>
                                        <property name="operandOne">
                                           <string><![CDATA[$FEATURE$]]></string>
                                        </property>
                                    </object>
                                </rules>
                                <installChildren>
                                    <object class="InstallComponent1">
                                        <property name="ruleExpression">
                                            <string><![CDATA[]]></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.1
                                                </property>
                                                <property name="operandOne">
                                             <string><![CDATA[$FEATURE$]]></string>
                                       </property>
                                             </object>
                                             <object class="CompareVariable">
                             <property name="ruleId">
                                <string><![CDATA[CIAV503]]></string> --copy2.2
              </property>
                                             </object>
                                            </rules>
                                        <installChildren>
                                            <object class="InstallDirCont">
                                                <property name="ruleExpression">
                                                    <string><![CDATA[]]></string>  --paste3
                                                </property>
                                                <property name="operandOne">
                                             <string><![CDATA[$FEATURE$]]></string>
                                     </property>
                                                <rules logicalOperation="OR">
                                                    <object class="CompareVariable1">
                                                        <property name="ruleId">
                                                            <string><![CDATA[CIAV100]]></string> --COPY3.1 </property>
                                                        <property name="operandOne">
                                                    <string><![CDATA[$FEATURE$]]></string>  </property>

                                                    </object>
                                                    <object class="CompareVariable2">
                                                        <property name="ruleId">
                                                            <string><![CDATA[CIAV200]]></string><!-- COPY3.2 -->
                                                        </property>
                                                        <property name="operandOne">
                                                   <string><![CDATA[$FEATURE$]]></string>
                                            </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>

「CIAV819」の値を copy1 の場所から paste1 の場所にコピーし、他の copy2 および copy3 の場所についても同様にコピーします。たとえば、paste1 の場所は次のようになります。

<property name="ruleExpression">
   <string><![CDATA[CIAV819]]></string>  ---paste1
</property>

paste2 の場所は次のようになります。

<property name="ruleExpression">
   <string><![CDATA[CIAV962 && CIAV503]]></string>  ---paste2
</property>

paste3 の場所は次のようになります。

<property name="ruleExpression">
   <string><![CDATA[CIAV100 || CIAV200]]></string>  ---paste3
</property>

その後、InstallAnywhere でこの xml ファイルを開くと、[ルール式] フィールドに入力された値が表示されます。以下の XSLT 変換を使用して出力を取得しています。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:output cdata-section-elements="string" />
<xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<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>
        <string>
           <xsl:for-each select="../rules[@logicalOperation='AND']/object">
                <xsl:value-of select="./rules/object/property/string" />
                <xsl:if test="position() &lt; count(../object)"><xsl:value-of select="' && '" /></xsl:if>
           </xsl:for-each>
        </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>

そして、この xml/xslt ファイルを処理している PHP ファイル (以下に示す) でこの XSLT を実行しています。

<?php
$xmldoc = new DOMDocument();
$xmldoc->load('ELS92.iap_xml');

$xsldoc = new DOMDocument();
$xsldoc->load('transform.xslt');

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

$result = $xslt->transformToDoc($xmldoc);
$result->save($xmldoc);
?>

CMDで「php test.php」のようなphpファイルを実行すると、xmlファイルが更新されますが、たとえば次のようになります。

  <property><string><![CDATA[CIAV100 || CIAV503]]></string></property>

それ以外の

<property name="Expression">
              <string><![CDATA[CIAV100 || CIAV503]]></string>
           </property>

2013 年 11 月 11 日月曜日: クエリが更新されました:

@Tim C : InstallAnywhere ソフトウェアで使用される長い名前を避けるために、いくつかのショートカットを作成しました。したがって、オブジェクト クラス 'InstallBundle' の元の名前は 'com.zerog.ia.installer.InstallBundle' であり、'InstallComponent' の名前は 'com.zerog.ia.installer.InstallComponent' です。したがって、xslt で、次のようにテンプレートにわずかな変更を加えました。

<xsl:template match="object[starts-with(@class, 'com.zerog.ia.installer.Install')]/property[@name='ruleExpression']">

また、もともと「com.zerog.ia.installer.actions.InstallDirCont」という名前の「InstallDirCont」オブジェクト クラスに一致する新しいテンプレートを追加しました。

<xsl:template match="object[starts-with(@class, 'com.zerog.ia.installer.actions.InstallDirCont')]/property[@name='ruleExpression']">

これはすべて私にとってはうまくいきます。ありがとうございます!

しかし、InstallAnywhere で生成されたファイルをリアルタイムで処理していると、PHP コードにいくつかの警告やエラーが見つかります。プロジェクト ファイルをお送りしてもよろしいですか。さらに詳しく調べて、xml ファイルの例外処理関数を見つけていただけないでしょうか。

クエリ更新日:2013 年 11 月 15 日:

@Tim C : こんにちはティム、申し訳ありませんが、さらに助けが必要です。この XSLT を新しいプロジェクト ファイル (xml) で実行した後、元の xml ファイルが空白になります。テンプレート ルールの一部が一致せず、それ以上の処理に失敗している可能性があります。しかし、よくわかりません。私のxmlファイルには、複数のInstallCOMponentおよびInstallDirCOntサブオブジェクトクラスがある多くのInstallBundleオブジェクトクラスが含まれていることを明確にしましょう。今、私はInstallBundleオブジェクトクラスの1つでそれを見つけました

 `<property name="bundleName">
<string><![CDATA[*** ** Database **]]</string>
</property>` 

、それにはInstallcomponentがあります

`<property name="componentName">
<string><![CDATA[Common]]></string>
</property>` 

以下の不適切な構造を持ち、さらに ruleId 値がないため、その ruleId 値を ruleExpression フィールドにコピーする必要はありません。xslt コードを更新してこの状態を回避し、InstallBundle に含まれるこの「データベース」の下にある他の installComponents のプロセスに従ってください。ありがとう

4

1 に答える 1

2

おそらく、変更したいプロパティ要素に一致するテンプレートを書くことから始めるべきです:

<xsl:template match="object[starts-with(@class, 'Install')]/property[@name='ruleExpression']">

ただし、この時点で行う必要があること、および例で行っていないことは、既存の要素をコピーするだけでなく、その属性もコピーすることです

<xsl:copy>
    <xsl:apply-templates select="@*" />
    <!-- Code to get rules -->
</xsl:copy>

実際の「ルール」要素を取得するには、この場合、次の最初の兄弟を取得したいだけのようです。

 <xsl:apply-templates select="following-sibling::rules[1]" mode="copy" />

がここにあるのmode="copy"は、通常のテンプレート マッチングルールを使用すると、後で実際のルールエレメントのコピーが壊れてしまうからです。

「ルール」に一致するこの特別なテンプレート内で、変数を作成して、「AND」または「OR」が使用されている操作を決定できます。

<xsl:template match="rules" mode="copy">
    <xsl:variable name="operator">
       <xsl:choose>
          <xsl:when test="@logicalOperation='OR'"> || </xsl:when>
          <xsl:otherwise> &amp;&amp; </xsl:otherwise>
       </xsl:choose>
    </xsl:variable>

これは、コードの繰り返しを回避し、すべてのルールで同じテンプレートを使用できることを意味します。

次に、ルールに必要なすべてのプロパティを書き出すだけです。

<xsl:for-each select="object/property[@name='ruleId']/string">
    <xsl:if test="position() > 1"><xsl:value-of select="$operator" /></xsl:if>
    <xsl:value-of select="." />
</xsl:for-each>

このXSLTを試してください

<xsl:stylesheet 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, 'Install')]/property[@name='ruleExpression']">
    <xsl:copy>
        <xsl:apply-templates select="@*" />
        <string>
            <xsl:apply-templates select="following-sibling::rules[1]" mode="copy" />
         </string>
    </xsl:copy>
</xsl:template>

<xsl:template match="rules" mode="copy">
    <xsl:variable name="operator">
       <xsl:choose>
          <xsl:when test="@logicalOperation='OR'"> || </xsl:when>
          <xsl:otherwise> &amp;&amp; </xsl:otherwise>
       </xsl:choose>
    </xsl:variable>
    <xsl:for-each select="object/property[@name='ruleId']/string">
        <xsl:if test="position() > 1"><xsl:value-of select="$operator" /></xsl:if>
        <xsl:value-of select="." />
    </xsl:for-each>
</xsl:template>

</xsl:stylesheet>

余談ですが、あなたの XSLT は整形式ではありません。のインスタンスは、&としてエスケープする必要があります&amp;。さらに、名前空間宣言を含むxsl:transform要素の前にxsl:outputステートメントがあります。

于 2013-10-31T13:06:18.100 に答える