0

次のように、いくつかの XML ファイルがあります。

ファイル: 1.xml

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <config>
       <info>
           <info1>val1</info1>
           <info2>val2</info2>
       </info>
       <info>
           <info1>val3</info1>
           <info2>val4</info2>
       </info>
   </config>

ファイル: 2.xml

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <config>
       <info>
           <info1>val5</info1>
           <info2>val6</info2>
       </info>
       <info>
           <info1>val7</info1>
           <info2>val8</info2>
       </info>
   </config>

ファイル: 3.xml

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <config>
       <info>
           <info1>val9</info1>
           <info2>val10</info2>
       </info>
       <info>
           <info1>val11</info1>
           <info2>val12</info2>
       </info>
   </config>

XSLT2.0 (saxon) を使用して、それらをマージし、各ノードにも追加したいと思います。

<info3>XXX</info3>

そしてまた

<file>filename.xml</file>

filename.xml は、情報のコピー元のファイルです。

出力は次のようになります。

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <config>
       <info>
           <info1>val1</info1>
           <info2>val2</info2>
           <info3>XXX</info3>
           <file>1.xml</file>
       </info>
       <info>
           <info1>val3</info1>
           <info2>val4</info2>
           <info3>XXX</info3>
           <file>1.xml</file>
       </info>
       <info>
           <info1>val5</info1>
           <info2>val6</info2>
           <info3>XXX</info3>
           <file>2.xml</file>
       </info>
       <info>
           <info1>val7</info1>
           <info2>val8</info2>
           <info3>XXX</info3>
           <file>2.xml</file>
       </info>
       <info>
           <info1>val9</info1>
           <info2>val10</info2>
           <info3>XXX</info3>
           <file>3.xml</file>
       </info>
       <info>
           <info1>val11</info1>
           <info2>val12</info2>
           <info3>XXX</info3>
           <file>3.xml</file>
       </info>
   </config>

これまでのところ、マージするファイルをリストする XML ファイル (merge.xml) を作成することで、ファイルをマージすることができました。

<mergeData newRoot="config">
   <filelist>
       <fileItem>1.xml</fileItem>
       <fileItem>2.xml</fileItem>
       <fileItem>3.xml</fileItem>
   </filelist>
</mergeData>

次の XSL (merge.xsl) を使用します。

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:xs="http://www.w3.org/2001/XMLSchema" version="2.0" exclude-result-prefixes="#all">
<xsl:param  name="new">
   <info>XXX</info>
</xsl:param>

<xsl:template match="/">
   <xsl:element name="{mergeData/@newRoot}">
      <xsl:apply-templates select="mergeData/fileList/fileItem"/>
   </xsl:element>
</xsl:template>

<xsl:template match="fileItem">
     <xsl:apply-templates select="document(translate(., '\', '/'))/config/*"/>
</xsl:template>

<xsl:template match="config/*">
   <xsl:copy>
       <xsl:copy-of select="node()"/>
       <xsl:copy-of select="$new"/>
   </xsl:copy>
   <file><xsl:value-of select="tokenize(document-uri(.), '/')[last()]"/></file>
 </xsl:template>

ファイル名を各情報に同時に取得するには、XSL をどのように変更すればよいですか。

4

2 に答える 2

0

本当にあなたがしなければならない唯一のことはfile、 の中に移動することですxsl:copy

例 (いくつかのマイナーなモッドを使用):

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema" version="2.0" exclude-result-prefixes="#all">
    <xsl:output indent="yes"/>
    <xsl:param  name="new">
        <info3>XXX</info3>
    </xsl:param>

    <xsl:template match="/">
        <xsl:element name="{mergeData/@newRoot}">
            <xsl:apply-templates select="mergeData/filelist/fileItem"/>
        </xsl:element>
    </xsl:template>

    <xsl:template match="fileItem">
        <xsl:apply-templates select="document(translate(., '\', '/'))/config/*"/>
    </xsl:template>

    <xsl:template match="config/*">
        <xsl:copy>
            <xsl:copy-of select="node(),$new"/>
            <file><xsl:value-of select="tokenize(document-uri(/), '/')[last()]"/></file>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

別のファイルcollection()を作成する代わりに、次を使用してこれを行うこともできます。mergeData.xml

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

    <xsl:param name="newRoot" select="'config'"/>
    <xsl:param name="new">
        <info3>XXX</info3>
    </xsl:param>

    <xsl:template match="/">
        <xsl:element name="{$newRoot}">
            <xsl:apply-templates select="collection('file:///C:/some/path?select=[0-9]*.xml')/*/info"/>
        </xsl:element>
    </xsl:template>

    <xsl:template match="info">
        <xsl:copy>
            <xsl:copy-of select="@*|node(),$new"/>
            <file><xsl:value-of select="tokenize(document-uri(/),'/')[last()]"/></file>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

Saxon を使用しているため、追加の代替手段の 1 つは、入力saxon:discard-document()と共に使用することです。mergeData.xmlに多数のファイルがリストされている場合mergeData.xml、これはメモリ消費を抑えるのに役立ちます。(Saxon PE または EE、または拡張機能を使用できる古いバージョンの Saxon が必要です。)

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

  <xsl:param name="new">
    <info3>XXX</info3>
  </xsl:param>

  <xsl:template match="/mergeData">
    <xsl:element name="{@newRoot}">
      <xsl:apply-templates select="filelist/fileItem"/>
    </xsl:element>
  </xsl:template>

  <xsl:template match="fileItem">
    <xsl:apply-templates select="document(.)/saxon:discard-document(.)/*/*" xmlns:saxon="http://saxon.sf.net/"/>          
  </xsl:template>

  <xsl:template match="info">
    <xsl:copy>
      <xsl:copy-of select="@*|node(),$new"/>
      <file><xsl:value-of select="tokenize(document-uri(/),'/')[last()]"/></file>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>
于 2013-10-24T22:32:16.787 に答える
0

次の XSLT は、必要な結果をもたらします。

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

  <xsl:output method="xml" encoding="UTF-8"/>

  <xsl:param  name="new">
    <info>XXX</info>
  </xsl:param>

  <xsl:template match="/mergeData">
    <config>

    <xsl:for-each select="filelist/fileItem">
      <xsl:variable name="filename" select="text()"/>

      <xsl:for-each select="document($filename)/config/info">
        <info>
          <xsl:copy-of select="./*"/>
          <xsl:element name="info{count(*)+1}">
            <xsl:value-of select="$new"/>
          </xsl:element>
          <file><xsl:value-of select="$filename"/></file>
        </info>

      </xsl:for-each>
    </xsl:for-each>

    </config>
  </xsl:template>

</xsl:stylesheet>

ノート:

  • これはすでに XSLT 1.0 で動作するため、XSLT 宣言を変更しました。
  • このアプローチは、事前定義されたサブ構造を使用したトップダウンnewRootであるため、入力ファイルの属性を使用しなくなりました。
  • 回答は、入力ファイルのベース名を抽出しませんが、マージ構成で指定されたフル パスを使用します。この単純化を元に戻したい場合があります。もちろん、使用tokenizeすると XSLT 2.0 または拡張機能にプッシュバックされます。
于 2013-10-24T20:22:11.477 に答える