2013-10-10 2 views
1

XML 노드에서 텍스트 노드를 한 위치에서 복사하여 다른 위치의 텍스트 노드에 붙여 넣기를 원합니다. 다음은 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> 

지금은 여기에 수행 할 작업입니다 : Object 클래스 InstallBundle1에서의

  1. 복사 "CIAV819"텍스트 노드 값 - 객체 클래스 CompareVariable을 사용하여 객체 클래스 인 InstallBundle1의 텍스트 노드에 붙여 넣습니다. InstallChildrenMain 바로 앞에

  2. "CIAV962"텍스트 노드 값을 O bject 클래스 InstallComponent1 - 객체 클래스 CompareVariable 및 붙여 넣기 그냥 InstallChildren

    전에 개체 클래스 InstallComponent1의의 노드를 텍스트
  3. Object 클래스의 InstallDirCont에서의
  4. 복사 "CIAV100"텍스트 노드 값 - 객체 클래스 CompareVariable1와 피연산자를 추가 "||" Object 클래스 InstallDirCont - CompareVariable2 객체 클래스의 "CIAV503"텍스트 노드 값을 복사하여 InstallChildren 바로 전에 객체 클래스 InstallDirCont의 텍스트 노드에 붙여 넣습니다.

나는이 조금 tidious 보이는 알고하지만 난이 수정이 필요합니다. 나는 완전히 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를 반환 :

객체 (DOMNodeList) # 2 (1) { [ "길이"] => 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를 추가해야합니까 업데이트? 규칙 식에 대한 템플릿 일치?

+0

복사 - 붙여 넣기 텍스트 편집기에서 당신이 할 일이다. 아마 당신이 묻지 않을 것이기 때문에 : o 노드를 복제하여 다른 곳에 삽입하고 싶습니까, 아니면 노드를 재배치하고 싶습니까? –

+0

@ Mike'Pomax'Kamermans : 안녕 마이크, 빠른 답장을 보내 주셔서 감사합니다. 나는 xml 편집기를 통해 이것을 수동으로하고 싶지 않다. 이 과정을 자동화하려고합니다. 그래서 노드를 복제하여 다른 곳에 삽입하고 싶습니다. – Celestial

+0

업데이트 된 답변을보고 사본 붙여 넣기 위치가 올바른지 여부를 알려주십시오. 그들은 당신의 묘사에서 나에게 완전히 명확하지 않습니다. – hielsnoppe

답변

1

다음은 입력 파일이 보이지만 주석이없는 것으로 가정합니다. 모든 솔루션에서 사용자의 필요에 맞게 XPath 선택기를 조정해야 할 수도 있습니다. 논리 PHP에서 수행되어야하는 경우

<?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> 

각각 PASTE 위치 위에 DOMXPath 루프를 사용하는 대신 getElementsByTagName() 시도 COPY 해당 위치의 데이터로 당긴다. 아래에서 XSLT 솔루션을 선호하기 때문에 이에 대해 자세히 설명하지 않겠습니다. 원하는 결과를 생산하기 위해 위의 XML 문서에 예제의 형태를 pick_a_meaningful_name.xslt로 저장 한 다음 변환을 적용하기 위해 내가 제안 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 
} 

.

<?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> 

XSLTProcessor을 사용하여 다음과 같을 수이 작업을 수행하는 PHP 코드의 최소한의 예 :

<?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 
관련 문제