3189


symfonyのCrawlerを使ってxmlにノードを追加したいと思い下記のように実装しました。

[code]

    //analyticsController.php
    use Symfony\Component\DomCrawler\Crawler;
    use Symfony\Component\CssSelector\CssSelector;
    
    public function analize() {
        $node = $this->generateDOMNode('ksj:station', 'xlink:href', '');
        $crawler->filter('ksj|Dataset ksj|RailroadSection')->addNode($node);
        $stations = $crawler->filter('ksj|Dataset ksj|RailroadSection ksj|station')->extract('xlink:href');
        var_dump($stations);
    }
    
    private function generateDOMNode($nodeName, $attr, $nodeValue){
        $dom = new \DOMDocument();
        $node = $dom->createElement($nodeName, $nodeValue);
        $attribute = $dom->createAttribute($attr);
        $attribute->value = "hello";
        $node->appendChild($attribute);
        return $node;
    }
    
[/code]

こちらを実行してもなぜか"hello"を返してくれません。

実際のxmlデータは下記のようななものです。

[code]

    //railRoad.xml
    <?xml version="1.0" encoding="UTF-8" ?>
    <ksj:Dataset>
     <ksj:RailroadSection gml:id="eb02_1">
      <ksj:location xlink:href="#cv_rss1"/>
      <ksj:railwayType>23</ksj:railwayType>
      <ksj:serviceProviderType>5</ksj:serviceProviderType>
      <ksj:railwayLineName>沖縄都市モノレール線</ksj:railwayLineName>
      <ksj:operationCompany>沖縄都市モノレール</ksj:operationCompany>
    </ksj:RailroadSection>
    </ksj:Dataset>
    
[/code]

上記のxmlデータを下記のように変えたいと思っています。

[code]

    <?xml version="1.0" encoding="UTF-8" ?>
    <ksj:Dataset>
     <ksj:RailroadSection gml:id="eb02_1">
      <ksj:location xlink:href="#cv_rss1"/>
      <ksj:railwayType>23</ksj:railwayType>
      <ksj:serviceProviderType>5</ksj:serviceProviderType>
      <ksj:railwayLineName>沖縄都市モノレール線</ksj:railwayLineName>
      <ksj:operationCompany>沖縄都市モノレール</ksj:operationCompany>
      <ksj:station>hello</ksj:station>
    </ksj:RailroadSection>
    </ksj:Dataset>
    
[/code]

よろしくお願い致します。


CC BY-SA 3.0
2015-01-06T03:20:06.957
3160
2015-01-06T11:06:06.540
288
question
php symfony2 xml
symfonyのCrawlerでxmlにノードを追加したい


XMLドキュメント自体を処理することが目的の場合、Symfony/DomCrawlerは使えません。
理由は、Symfony/DomCrawlerは、各種メソッド（`filter()`など）実行のたびに、状態が適用された「新しいCrawlerインスタンス」を返すようになっているからです。
提示されているコードだと、

[code]

    $crawler->filter('ksj|Dataset ksj|RailroadSection')->addNode($node);
    
[/code]

この最初の `filter()`
で新しい`Crawler`インスタンスが作られます。新しい`Crawler`は、セレクタで指定したノードだけを持ち、元のXMLドキュメント（に対応するCrawler）とはまったく別のインスタンスになります。ここにノードを追加したとしても、元のドキュメント構造は変化しません。

XMLを操作したい場合は、PHPが持つDOM関連機能（DOMとXPath) あたりで解決してはいかがでしょうか。

例に挙げられている処理（XMLドキュメントの特定の箇所に、ノードを追加する）であれば、次のようなコードになります。

[code]

    <?php
    $document = new DOMDocument();
    $document->loadXML(file_get_contents('railroad.xml'));
    
    $xpath = new DOMXpath($document);
    $nodes = $xpath->query("//ksj:Dataset/ksj:RailroadSection");
    
    $adding = generateDOMNode('ksj:station', 'xlink:href', '', $document);
    
    foreach ($nodes as $node) {
        $node->appendChild($adding);
    }
    
    function generateDOMNode($nodeName, $attr, $nodeValue, $document)
    {
        $node = $document->createElement($nodeName, $nodeValue);
        $node->setAttribute($attr, "hello");
        return $node;
    }
    
    $xml = $document->saveXML();
    
    // stationのxlinkだけを取り出す
    $document2 = new DOMDocument();
    $document2->loadXML($xml);
    $xpath = new DOMXpath($document2);
    $stations = $xpath->query("//ksj:Dataset/ksj:RailroadSection/ksj:station/@xlink:href");
    
    foreach ($stations as $station) {
        echo $station->value;
    }
    
[/code]

（参考までに、namespaceを付加したXMLファイルも貼っておきます）

[code]

    <?xml version="1.0" encoding="UTF-8" ?>
    <ksj:Dataset xmlns:ksj="http://nlftp.mlit.go.jp/ksj/schemas/ksj-app"  xmlns:gml="http://www.opengis.net/gml/3.2" xmlns:xlink="http://www.w3.org/1999/xlink">
        <ksj:RailroadSection gml:id="eb02_1">
            <ksj:location xlink:href="#cv_rss1"/>
            <ksj:railwayType>23</ksj:railwayType>
            <ksj:serviceProviderType>5</ksj:serviceProviderType>
            <ksj:railwayLineName>沖縄都市モノレール線</ksj:railwayLineName>
            <ksj:operationCompany>沖縄都市モノレール</ksj:operationCompany>
        </ksj:RailroadSection>
    </ksj:Dataset>
    
[/code]

なお、XPathの構文などについては[MSDNのページ](http://msdn.microsoft.com/ja-
jp/library/ms256086\(v=vs.110\).aspx)が参考になります。


CC BY-SA 3.0
2015-01-06T11:06:06.540
3189
2015-01-06T11:06:06.540
5444
3160
answer