0

これは一日中私の頭をやっています。あなたは私を助けることができます?!単純なxmlファイルがあります。xsltを使用してyamlファイルに変換したいと思います。問題は次のとおりです。

  1. xmlタグから特定の値のみをキャッチ し、それらを特定のyamlディクショナリ(作業、アドレス)に配置するように出力を整理する必要があります
  2. 一部のxmlタグにはnames()またはattrs()があり、事前に予測することはできません。したがって、names()やposition()、またはその他のロジックでそれらを取得することはできません。私はいくつかの仮定をすることができますが、すべてのタグについてではありません...
  3. 出力をフォーマットしているときに、必要な値を選択した後、yamlファイルの辞書キー(work、address )を設定するのは非常に難しいと思います-ofertのすべての子(私は必要ありません)にキーを設定するか、個々の要素ごとにキーを設定できますが、これは私が望むものではありません。

このことを考慮:

<data>
   <info>some info</info>
   <data>some data</data>
   <list>
         <ofert>
            <unknow>....</unknow>
            <unknow1>....</unknow1>
            <id>00934</id>
            <name>Bob</name>
            <street>Euston rd.</street>
            <postcode>SE23GH</postcode>
            <job>IT</job>
            <position>boss</position>
            <unknow>....</unknow>
            <unknow4>....</unknow4>
            <unknow2>....</unknow2>
            <unknow3>....</unknow3>
         </ofert>
   </list>
</data>

次のような出力が必要です。

データ:
    情報: ....
    データ: ....
        リスト:
            ofert:
                id:00934
                名前:ボブ
                住所:{通り:Euston rd、郵便番号:SE23GH}
                仕事:{仕事:IT、役職:上司}
                その他:{不明:.....、不明1:....}


4

1 に答える 1

1

これは、「other:」yaml 要素を含まない単純な XSLT 1.0 ソリューションです ...

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:strip-space elements="*"/>

<xsl:template match="@*" />

<xsl:template match="*">
  <xsl:call-template name="indent">
   <xsl:with-param name="spaces" select="count(ancestor::*)"/>
  </xsl:call-template>
  <xsl:value-of select="concat( local-name(), ': ', text(), '&#x0A;')"/>
  <xsl:apply-templates select="*" />
</xsl:template>

<xsl:template match="ofert">
  <xsl:variable name="indent" select="count(ancestor::*)" />
  <xsl:call-template name="indent">
   <xsl:with-param name="spaces" select="$indent"/>
  </xsl:call-template>
  <xsl:value-of select="concat( local-name(), ': ', text(), '&#x0A;')"/>
  <xsl:apply-templates select="id" />
  <xsl:apply-templates select="name" />
  <xsl:call-template name="indent">
   <xsl:with-param name="spaces" select="$indent + 1"/>
  </xsl:call-template>
  <xsl:value-of select="concat(
    'address: {street: ', street/text(),
    ', postcode: ', postcode,' }&#x0A;')"/>
  <xsl:call-template name="indent">
   <xsl:with-param name="spaces" select="$indent + 1"/>
  </xsl:call-template>
  <xsl:value-of select="concat(
     'work: {job: ', job,
  ', position: ', position, ' }&#x0A;')"/>
</xsl:template>


<xsl:template name="indent">
  <xsl:param name="spaces" />
  <xsl:if test="$spaces > 0">
   <xsl:value-of select="' '"/>
   <xsl:call-template name="indent">
    <xsl:with-param name="spaces" select="$spaces - 1"/>
   </xsl:call-template>
  </xsl:if>
</xsl:template>

</xsl:stylesheet>

XSLT 2.0 ソリューションは、はるかに単純です。XSLT 1.0 に制約されていない場合はお知らせください。

時間があれば、ソリューションを更新して「other:」要素を含めます。基本的には、名前付きテンプレートを定義して、 address: 、 work: 、 other: などの関連配列を生成するだけです。入力パラメーターには、インデント レベル、ラベル ('address' など)、および連想配列メンバーのリストが含まれます。ノード。理解していただければ幸いです。


アップデート

「その他」の yaml 要素を含む XSLT 2.0 バージョンは次のとおりです ...

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="2.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:fn="http://www.w3.org/2005/xpath-functions"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  xmlns:zzart="http://stackoverflow.com/questions/11192960">
<xsl:output method="text"/>
<xsl:strip-space elements="*"/>

<xsl:variable name="indent-unit" select = "'  '" />

<xsl:function name="zzart:indent" as="xs:string">
 <xsl:param name="level" as="xs:integer"/>
 <xsl:value-of select="fn:string-join( for $in in 1 to $level return $indent-unit, '')" />
</xsl:function>

<xsl:template match="@*" />

<xsl:template match="*">
  <xsl:value-of select="concat( zzart:indent( count(ancestor::*)), local-name(), ': ', text(), '&#x0A;')"/>
  <xsl:apply-templates select="*" />
</xsl:template>

<xsl:template match="ofert">
  <xsl:variable name="level" select="count(ancestor::*)" />
  <xsl:variable name="indent" select="zzart:indent( $level)" />
  <xsl:value-of select="concat( $indent, local-name(), ': ', text(), '&#x0A;')"/>
  <xsl:apply-templates select="id" />
  <xsl:apply-templates select="name" />
  <xsl:call-template name="associative-array">
   <xsl:with-param name="level" select="$level + 1" />
   <xsl:with-param name="array-name" select="'address'" />
   <xsl:with-param name="array-members" select="(street, postcode)" />
  </xsl:call-template>
  <xsl:call-template name="associative-array">
   <xsl:with-param name="level" select="$level + 1" />
   <xsl:with-param name="array-name" select="'work'" />
   <xsl:with-param name="array-members" select="(job, position)" />
  </xsl:call-template>

  <xsl:call-template name="associative-array">
   <xsl:with-param name="level" select="$level + 1" />
   <xsl:with-param name="array-name" select="'other'" />
   <xsl:with-param name="array-members" select="*[not(self::id)][not(self::name)]
                                                 [not(self::street)][not(self::postcode)]
                                                 [not(self::job)][not(self::position)]" />
  </xsl:call-template>

</xsl:template>

<xsl:template name="associative-array">
 <xsl:param name="level" as="xs:integer" />
 <xsl:param name="array-name" as="xs:string" />
 <xsl:param name="array-members"/>
 <xsl:value-of select="concat( zzart:indent( $level), $array-name, ': {')" />
 <xsl:for-each select="$array-members">
  <xsl:value-of select="concat( local-name(), ': ', text(), if (position() != last()) then ', ' else ' }&#x0A;')" />
 </xsl:for-each>    
</xsl:template>

</xsl:stylesheet>
于 2012-06-25T17:12:13.097 に答える