2

XMLファイルで同様のXMLタグを連結するには、どうすればこれを処理できますか

次の形式の XML があります::

<addressbook>
 <address>
    <first-name>Chester Hasbrouck</first-name>
     <Descritpion>Hi</Descritpion>
     <Descritpion>This is Chester </Descritpion>
   <street>1234 Main Street</street>
  <city>Sheboygan</city>
  <state>WI</state>
  <zip>48392</zip>
 </address>
 <address>
    <first-name>Mary</first-name>
     <Descritpion>Hi</Descritpion>
     <Descritpion>This is Mary </Descritpion>
     <Descritpion>Bye</Descritpion>
     <street>283 First Avenue</street>
  <city>Skunk Haven</city>
  <state>MA</state>
  <zip>02718</zip>
 </address>
</addressbook>

次の形式でこれが必要です。誰かがそのために XSLT を提案してください。

<addressbook>
 <address>
    <first-name>Chester Hasbrouck</first-name>
     <Descritpion>Hi | This is Chester </Descritpion>
   <street>1234 Main Street</street>
  <city>Sheboygan</city>
  <state>WI</state>
  <zip>48392</zip>
 </address>
 <address>
    <first-name>Mary</first-name>
     <Descritpion>Hi | This is Mary | Bye</Descritpion>
     <street>283 First Avenue</street>
  <city>Skunk Haven</city>
  <state>MA</state>
  <zip>02718</zip>
 </address>
</addressbook>
4

3 に答える 3

1

この変換:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

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

 <xsl:template match="Descritpion[not(preceding-sibling::*[1][self::Descritpion])]">
  <Descritpion>
   <xsl:value-of select="."/>
   <xsl:apply-templates select="following-sibling::Descritpion/text()"/>
  </Descritpion>
 </xsl:template>

 <xsl:template match="Descritpion/text()">
   <xsl:value-of select="concat(' | ', .)"/>
 </xsl:template>
 <xsl:template match="Descritpion"/>
</xsl:stylesheet>

提供された XML ドキュメントに適用した場合:

<addressbook>
    <address>
        <first-name>Chester Hasbrouck</first-name>
        <Descritpion>Hi</Descritpion>
        <Descritpion>This is Chester </Descritpion>
        <street>1234 Main Street</street>
        <city>Sheboygan</city>
        <state>WI</state>
        <zip>48392</zip>
    </address>
    <address>
        <first-name>Mary</first-name>
        <Descritpion>Hi</Descritpion>
        <Descritpion>This is Mary </Descritpion>
        <Descritpion>Bye</Descritpion>
        <street>283 First Avenue</street>
        <city>Skunk Haven</city>
        <state>MA</state>
        <zip>02718</zip>
    </address>
</addressbook>

必要な正しい結果が生成されます

<addressbook>
   <address>
      <first-name>Chester Hasbrouck</first-name>
      <Descritpion>Hi | This is Chester </Descritpion>
      <street>1234 Main Street</street>
      <city>Sheboygan</city>
      <state>WI</state>
      <zip>48392</zip>
   </address>
   <address>
      <first-name>Mary</first-name>
      <Descritpion>Hi | This is Mary  | Bye</Descritpion>
      <street>283 First Avenue</street>
      <city>Skunk Haven</city>
      <state>MA</state>
      <zip>02718</zip>
   </address>
</addressbook>

説明:

  1. アイデンティティ ルールは、すべてのノードを「そのまま」コピーします。

  2. Descritpion要素は通常、空の本文のテンプレート マッチングで ID テンプレートをオーバーライドすることにより、無視または削除されますDescritpion

  3. Descritpion直前の兄弟要素がそれ自体ではない要素のみが、Descritpion別のオーバーライド テンプレートによって特別に扱われます。Descritpionここでは、要素の文字列値がコピーされ、テンプレートが次の兄弟要素のすべての text-node-children に適用されます。

  4. 要素の text-node-child に一致するテンプレートはDescritpion、必要なテキスト連結を実装します。

于 2012-06-20T12:55:53.870 に答える
0

これを行うには、ID変換に基づいて構築できますが、関心のある要素を処理するためのルールを追加します

まず、子要素を含まない要素を一致させる必要があると思います

<xsl:template match="*[not(*)]" priority="1">

次に、これにコードを追加して現在のテキスト値を出力し、同じ名前の後続のすべての兄弟のテキスト値を選択します(前に区切り文字が付いて出力されます)。

<xsl:apply-templates 
   select="following-sibling::*[local-name() = local-name(current())]/text()" 
   mode="concat"/>

また、前の兄弟と同じ名前の要素を無視して、2回出力されないように、テンプレートを追加する必要があります。

<xsl:template 
    match="*[not(*)][local-name() = local-name(preceding-sibling::*[1])]" 
    priority="2" />

ここでpriority属性を使用していることに注意してください。これにより、XSLTプロセッサーは、優先度の高いものを最初に照合します。

これが完全なXSLTです

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

   <xsl:template match="*[not(*)]" priority="1">
      <xsl:copy>
         <xsl:value-of select="normalize-space(.)"/>
         <xsl:apply-templates select="following-sibling::*[local-name() = local-name(current())]/text()" mode="concat"/>
      </xsl:copy>
   </xsl:template>

   <xsl:template match="*[not(*)][local-name() = local-name(preceding-sibling::*[1])]" priority="2"/>

   <xsl:template match="text()" mode="concat">
      <xsl:value-of select="concat(' | ', normalize-space(.))"/>
   </xsl:template>

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

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

<addressbook>
   <address>
      <first-name>Chester Hasbrouck</first-name>
      <Descritpion>Hi | This is Chester</Descritpion>
      <street>1234 Main Street</street>
      <city>Sheboygan</city>
      <state>WI</state>
      <zip>48392</zip>
   </address>
   <address>
      <first-name>Mary</first-name>
      <Descritpion>Hi | This is Mary | Bye</Descritpion>
      <street>283 First Avenue</street>
      <city>Skunk Haven</city>
      <state>MA</state>
      <zip>02718</zip>
   </address>
</addressbook>
于 2012-06-20T12:31:51.557 に答える
0

もう 1 つの方法を次に示します。

注意すべき点として、このソリューションでは出力ドキュメントの順序が維持されません (つまり、<Descritpion>要素の直下に新しい要素が作成されません<first-name>)。それが重要な場合は、提供されている他のソリューションをご覧ください。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:output omit-xml-declaration="no" indent="yes"/>
  <xsl:strip-space elements="*"/>

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

  <!-- TEMPLATE #2 -->
  <xsl:template match="address">
    <xsl:copy>
      <xsl:apply-templates/>
      <Descritpion>
        <xsl:apply-templates select="Descritpion/text()"/>
      </Descritpion>
    </xsl:copy>
  </xsl:template>

  <!-- TEMPLATE #3 -->
  <xsl:template match="Descritpion/text()">
    <xsl:value-of select="." />
    <xsl:if test="position() != last()"> | </xsl:if>    
  </xsl:template>

  <!-- TEMPLATE #4 -->
  <xsl:template match="Descritpion" />
</xsl:stylesheet>

提供された XML ドキュメントでこれが提供されている場合:

<?xml version="1.0" encoding="UTF-8"?>
<addressbook>
  <address>
    <first-name>Chester Hasbrouck</first-name>
    <Descritpion>Hi</Descritpion>
    <Descritpion>This is Chester </Descritpion>
    <street>1234 Main Street</street>
    <city>Sheboygan</city>
    <state>WI</state>
    <zip>48392</zip>
  </address>
  <address>
    <first-name>Mary</first-name>
    <Descritpion>Hi</Descritpion>
    <Descritpion>This is Mary </Descritpion>
    <Descritpion>Bye</Descritpion>
    <street>283 First Avenue</street>
    <city>Skunk Haven</city>
    <state>MA</state>
    <zip>02718</zip>
  </address>
</addressbook>

...目的の結果が生成されます。

<?xml version="1.0" encoding="UTF-8"?><addressbook>
  <address>
    <first-name>Chester Hasbrouck</first-name>
    <street>1234 Main Street</street>
    <city>Sheboygan</city>
    <state>WI</state>
    <zip>48392</zip>
    <Descritpion>Hi | This is Chester </Descritpion>
  </address>
  <address>
    <first-name>Mary</first-name>
    <street>283 First Avenue</street>
    <city>Skunk Haven</city>
    <state>MA</state>
    <zip>02718</zip>
    <Descritpion>Hi | This is Mary  | Bye</Descritpion>
  </address>
</addressbook>

説明:

  • テンプレート #1:「アイデンティティ テンプレート」はすべてをそのままコピーします。

  • テンプレート #2:<address>このテンプレートは、各要素をそのままコピーし、新しい<Descritpion>要素を作成し、一致するテンプレートからの結果でその新しい要素を埋めるように XSLT プロセッサに指示しますDescritpion/text()

  • テンプレート #3:このテンプレートはテンプレート #2 の結果を処理します。特に、すべての古い<Descritpion>要素からテキストをコピーし、最後の要素に到達するまで|、結果の間に a を配置します。

  • テンプレート #4:<Descritpion>このテンプレートは、ソース ドキュメントから元の要素を削除します。

于 2012-06-20T13:59:44.913 に答える