0

私は次のXMLを持っています:

<person-list>
  <pid>100</pid>
  <pname>Tom Jones</pname>
  <pdescription>Some Text</pdescription>
  <pid>101</pid>
  <pname>John Thomas</pname>
</person-list>

次の結果を取得したいと思います。

<person-list>
  <person>
    <pid>100</pid>
    <pname>Tom Jones</pname>
    <pdescription>Some Text</pdescription>
  </person>
  <person>
    <pid>101</pid>
    <pname>John Thomas</pname>
  </person>
</person-list>

これを達成することは可能ですか?

4

3 に答える 3

2

XSLT1.0でこれを行う1つの方法は、 person-listの下の非pid要素を最初の最も前のpid要素でグループ化するキーを定義することです。

<xsl:key 
   name="fields" 
   match="person-list/*[not(self::pid)]" 
   use="generate-id(preceding-sibling::pid[1])" />

次に、person-list要素には、 pid要素のみを選択します。

<xsl:apply-templates select="pid" />

そして、pidに一致するテンプレート内で、 person要素を作成し、キーを使用して他の要素を出力します。

<xsl:apply-templates select="key('fields', generate-id())" />

これが完全なXSLTです

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:output method="xml" indent="yes"/>
   <xsl:key name="fields" match="person-list/*[not(self::pid)]" use="generate-id(preceding-sibling::pid[1])" />
   <xsl:template match="person-list">
      <person-list>
         <xsl:apply-templates select="pid" />
      </person-list>
   </xsl:template>

   <xsl:template match="pid">
      <person>
         <xsl:copy-of select="." />
         <xsl:apply-templates select="key('fields', generate-id())" />
      </person>
   </xsl:template>

   <xsl:template match="@*|node()" name="identity">
      <xsl:copy>
         <xsl:apply-templates select="@*|node()"/>
      </xsl:copy>
   </xsl:template>
</xsl:stylesheet>

サンプルXMLに適用すると、次のように出力されます。

<person-list>
  <person>
    <pid>100</pid>
    <pname>Tom Jones</pname>
    <pdescription>Some Text</pdescription>
  </person>
  <person>
    <pid>101</pid>
    <pname>John Thomas</pname>
    <pdescription></pdescription>
  </person>
</person-list>

このアプローチでは、XSLTを修正することなく、各人の入力ドキュメントにさらにフィールドを追加できることに注意してください。

また、既存の要素をコピーするための「ID変換」の使用にも注意してください。

于 2012-09-07T10:05:48.980 に答える
1

XSLT 2.0 ソリューション:

<xsl:template match="person-list">
  <xsl:copy>
    <xsl:for-each-group select="*" group-starting-with="pid">
      <person>
        <xsl:copy-of select="current-group()"/>
      </person>
    </xsl:for-each-group>
  </xsl:copy>
</xsl:template>
于 2012-09-07T11:09:31.363 に答える
0

はい、それを行う方法があります。たとえば、「pid」要素を見つけて、「following-sibling」を使用して次の 2 つの要素と結合し、コピーしたタグを削除できます。

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

 <!-- IdentityTransform -->
 <xsl:template match="/ | @* | node()">
       <xsl:copy>
             <xsl:apply-templates select="@* | node()" />
       </xsl:copy>
</xsl:template>

<xsl:template match="/person-list/pid">
<person>
  <pid><xsl:value-of select="." /></pid>
  <pname><xsl:value-of select="following-sibling::*" /></pname>
  <pdescription><xsl:value-of select="following-sibling::*/following-sibling::*" />    </pdescription>
</person>
</xsl:template>
<xsl:template match="/person-list/pname" />
<xsl:template match="/person-list/pdescription"/>

</xsl:stylesheet>
于 2012-09-07T09:55:35.360 に答える