web-dev-qa-db-ja.com

xmlstarletを使用してXMLのフィールドをタグに変換できますか?

たとえば、タグのフィールドをそのタグ内のタグに変換したい

<book name="Data Structure" price="250" pages="350"/>

<book name="Data Structure"> 
<price>250</price>
<pages>350</pages>
</book>

Xmlstarletまたはsedを使用してLinuxコマンドラインでこの操作を実行したい

3
krishna

process.xsl

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="yes"/>

  <xsl:template match="//book">
    <xsl:element name="book">
      <xsl:apply-templates select="./@*"/>
    </xsl:element>
  </xsl:template>

  <xsl:template match="book/@*">
      <xsl:if test="name() = 'name'">
    <xsl:attribute name="{name()}">
      <xsl:value-of select="."/>
    </xsl:attribute>
      </xsl:if>
      <xsl:if test="name() != 'name'">
    <xsl:element name="{name()}">
      <xsl:value-of select="."/>
    </xsl:element>
      </xsl:if>
  </xsl:template>
</xsl:stylesheet>

input.xml

<book name="Data Structure" price="250" pages="350"/>

コマンド:

xsltproc process.xsl input.xml

出力:

<?xml version="1.0"?>
<book name="Data Structure">
  <price>250</price>
  <pages>350</pages>
</book>
3
neuron

お願いします-sedを使用しないでください-それは仕事に適したツールではありません。

私は自分でPerlを使います:

_#!/usr/bin/env Perl
use strict;
use warnings;

use XML::Twig;

my $twig = XML::Twig->new( 'pretty_print' => 'indented_a' );
$twig->parsefile ( 'your_file.xml' );

foreach my $thing ( $twig -> root -> children ) {

    my $newthing = $twig -> root -> insert_new_elt($thing->tag);
    foreach my $key ( keys %{$thing -> atts()} ) {
        $newthing -> insert_new_elt($key, $thing -> att($key));
    }
    $thing -> delete;
}

$twig->print;
_

出力:

_<root>
  <book>
    <pages>350</pages>
    <name>Data Structure</name>
    <price>250</price>
  </book>
</root>
_

(匿名の)ハッシュatt()を使用しているため、これは非常に簡単です。 1つの属性を選択するには、もう少し行う必要があります-実行することを定義する必要がありますkeepnameそして、それを親要素の属性として挿入します。

これはmapを使用しますが、これは少し頭痛の種になる可能性があります。

_#!/usr/bin/env Perl
use strict;
use warnings;
use Data::Dumper;

use XML::Twig;

my %keep_att = ( name => 1 );
my $twig = XML::Twig->new( 'pretty_print' => 'indented_a' );
$twig->parse( \*DATA );

foreach my $thing ( $twig->root->children ) {
    my $newthing = $twig->root->insert_new_elt( $thing->tag,
        { map { $_ => $thing->att($_) } keys %keep_att } );

    foreach my $key ( keys %{ $thing->atts() } ) {
        next if $keep_att{$key};
        $newthing->insert_new_elt( $key, $thing->att($key) );
    }
    $thing->delete;
}

$twig->print;

__DATA__
<root>
<book name="Data Structure" price="250" pages="350"/>
</root>
_

これにより、次のものが生成されます。

_<root>
  <book name="Data Structure">
    <price>250</price>
    <pages>350</pages>
  </book>
</root>
_

さて、そのmapで何が起こっているのかというと、基本的に保持したい属性を分割し、それらを新しい要素に再挿入し、要素を再挿入しますしない =維持し、子供に変えたい。

このようなビット:

_foreach my $thing ( $twig->root->children ) {

    my %attributes = %{$thing->atts()};
    my %new_children; 
    foreach my $attr ( keys %attributes ) {
       if ( $keep_att{$attr} ) { 
           #leave it in %attributes; 
       }
       else {
           $new_children{$attr} = $attributes{$attr}; 
           delete $attributes{$attr}
       }
    }
    print Dumper \%attributes;
    print Dumper \%new_children;

    my $newthing = $twig->root->insert_new_elt( $thing->tag,
        { %attributes } );

    foreach my $key ( keys %new_children ) {
        $newthing->insert_new_elt( $key, $new_children{$key} );
    }
    $thing->delete;
}
_
0
Sobrique