1

XSLT には、remove()シーケンス用の関数があります。シーケンスと位置を指定すると、シーケンスから指定された位置の項目を引いたものを返します。

問題は、実際の XSLT ファイルでこの関数を使用するにはどうすればよいかということです。

コンテキストを完全に欠いた関数仕様の単なる逆流ではない例についての言及を見つけた唯一の場所は、http: //books.google.com/books?id=W6SpffnfEPoC&pg=PA776&lpg=PA776&dq=xslt+です。 %22remove+function%22&source=bl&ots=DQQrnXF_nB&sig=nrJtpEvYjBaZU0K8iAtdPTGUIbI&hl=en&sa=X&ei=QOq8T7aPDOyI6AHh-JBP&ved=0CEQQ6AEwAQ#v=onepage&q=xslt%20%22remove%20function%22&f=false

残念ながら、スタイルシートの例は 777 ページと 778 ページにありますが、もちろん含まれていません。そして、私はその本を所有していません。

remove()では、実際のスタイルシートで XSLT 関数を使用した例はありますか?

編集:もう少し具体的な例を挙げましょう。

XSLT にシーケンスがあります。このシーケンスは、テキスト ファイルのすべての行で構成されています。

<xsl:variable name="lines" select="tokenize(unparsed-text($filePath), '\r?\n')" />

これらの行はすべてレコードです...1 つを除いて、レコード数がわかります。そのため、その行を見つけるための次のコードがあります。

<xsl:variable name="recordCount">
  <xsl:for-each select="$lines[position()]">
    <xsl:variable name="i" select="position()" />
    <xsl:analyze-string select="$lines[$i]" regex="RECORD COUNT = \d+">
      <xsl:matching-substring>
        <xsl:value-of select="replace($lines[$i], '[^0-9]', '')" />
      </xsl:matching-substring>
    </xsl:analyze-string>
  </xsl:for-each>
</xsl:variable>

行をループして実際のすべてのレコードを取得する前に上記を実行するため、ここでの目標は、「RECORD COUNT」行$linesを見つけたときにシーケンスから削除することです。そうすれば、レコードを取得してループするときに、「これは実際にはレコードではなく、実際には RECORD COUNT 行ですか? "

編集 (2): Martin Honnen の回答に基づいて、私の最終的な XSLT:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
  <!-- I want to produce an XML document. -->
  <xsl:output method="xml" indent="yes" />

  <!-- Path to input text file. -->
  <xsl:param name="filePath" select="TestFile.txt" />

  <!-- Regex in replace() removes leading and trailing blank space. -->
  <xsl:variable name="text" select="replace(unparsed-text($filePath), '(^[\r\n]*\s*[\r\n]+)|([\r\n]+\s*[\r\n]*$)', '')" />

  <!-- Regex in tokenize() sets the delimiter to be any blank space between record lines. -->
  <!-- This effectively removes any blank lines. -->
  <xsl:variable name="lines" select="tokenize($text, '[\r\n]+\s*[\r\n]*')" />

  <!-- This finds the "RECORD COUNT = ?" line. -->
  <xsl:variable name="recordCountIndex"
    select="for $pos in 1 to count($lines) return $pos[matches($lines[$pos], 'RECORD COUNT = \d+')]" />

  <!-- Regex in replace() strips everything that's not a number, leaving only the numeric count. -->
  <!-- Example: "RECORD COUNT = 25" -> "25" -->
  <xsl:variable name="recordCount" select="replace($lines[$recordCountIndex], '[^0-9]', '')" />

  <xsl:template name="main">
    <root>
      <recordCount>
        <!-- The record count value being inserted. -->
        <xsl:value-of select="$recordCount" />
      </recordCount>
      <records>
        <!-- Iterate over the $lines minus the line containing the record count. -->
        <xsl:for-each select="remove($lines, $recordCountIndex)">
          <!-- Items in each record, split by blank space. -->
          <!-- Example: "a b c" -> "[a, b, c]" -->
          <xsl:variable name="record" select="tokenize(., ' ')[position()]" />
          <record>
            <aThing>
              <xsl:value-of select="$record[1]" />
            </aThing>
            <aDifferentThing>
              <xsl:value-of select="$record[2]" />
            </aDifferentThing>
            <someStuff>
              <xsl:value-of select="$record[3]" />
            </someStuff>
          </record>
        </xsl:for-each>
      </records>
    </root>
  </xsl:template>
</xsl:stylesheet>
4

2 に答える 2

1

あなたの混乱がどこにあるかを正確に理解するのは難しいです。

まず、シーケンスからアイテムを削除しても、ツリーからノードが削除されることはありません。(私は、「ノードを含む」シーケンスについての仕様の説明に反対しました。ノードへの参照を含むものと考える方がよいと思います。したがって、ノードに影響を与えないノードへの参照を削除します。とにかくそれ自体。)

第二に、変数は手続き型言語で記述されることがあるため、変数について考えているようです。値を含む名前付きボックスは、異なる時間に異なる値を含む可能性があります。XSLT変数とXQuery変数をそのように考えないでください。それらを名前付きの値と考えてください。「上書き」は意味のある操作ではありません。

最後に、ユースケース。私がremoveを使用する最も一般的な方法は、シーケンスの末尾を取得することですremove($seq, 1)subsequence($seq, 2)asまたはas$seq[position() gt 1]と書くこともできますがremove()、キーストロークが少なくなります。remove()正直なところ、他の方法で使った実例を考えるのに苦労していて、思いつかない。

それはあなたの質問についての観察に私を導きます。「この機能の使い方」を尋ねるのは、かなり奇妙な質問です。私たちが人々に尋ねることを期待しているのは、「どうすればこの問題を解決できるか」です。時々、人々が機能の使い方を尋ねるとき、彼らは特定の問題を解決するのに苦労していますが、彼らは私たちに問題が何であるかを教えてくれません。あなたが私たちに言ったならそれは助けになるでしょう:remove()解決策の一部ではない良いチャンスがあります。

于 2012-05-23T16:13:05.857 に答える
1

良い

<xsl:variable name="seq1" select="1, 2, 3, 4"/>
<xsl:variable name="seq2" select="remove($seq1, 2)"/>

変数の値seq2を 3 つの数値 1、3、4 のシーケンスにします。

[編集]

編集した問題の説明に基づく例を次に示します。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  exclude-result-prefixes="xs"
  version="2.0">

  <xsl:output method="text"/>

  <xsl:param name="filePath" select="'test2012052301.txt'"/>

  <xsl:variable name="lines" select="tokenize(unparsed-text($filePath), '\r?\n')" />

  <xsl:variable name="index" as="xs:integer"
    select="for $pos in 1 to count($lines) return $pos[matches($lines[$pos], 'RECORD COUNT = [0-9]+')]"/>

  <xsl:variable name="recordCount" as="xs:integer"
    select="xs:integer(replace($lines[$index], '[^0-9]', ''))"/>

  <xsl:template name="main">
    <xsl:value-of select="remove($lines, $index)" separator="&#10;"/>
    <xsl:text>count is: </xsl:text>
    <xsl:value-of select="$recordCount"/>
  </xsl:template>

</xsl:stylesheet>

たとえば、テキストファイルが

foo
bar
RECORD COUNT = 3
baz

スタイルシート出力

foo
bar
baz
count is: 3

[edit2] セクションを短くできると思います

  <records>
    <!-- The $lines sequence trimmed down to only consist of valid records. -->
    <!-- (I have found no way around having this intermediate variable.) -->
    <xsl:variable name="records" select="remove($lines, $recordCountIndex)" />
    <xsl:for-each select="$records[position()]">
      <!-- Variable for iteration. Perhaps there's a more elegant way to do this. -->
      <xsl:variable name="i" select="position()" />
      <!-- Items in each record, split by blank space. -->
      <!-- Example: "a b c" -> "[a, b, c]" -->
      <xsl:variable name="recordItems" select="tokenize($records[$i], ' ')" />
      <record>
        <item1>
          <xsl:value-of select="$recordItems[1]" />
        </item1>
        <item2>
          <xsl:value-of select="$recordItems[2]" />
        </item2>
        <item3>
          <xsl:value-of select="$recordItems[3]" />
        </item3>
      </record>
    </xsl:for-each>
  </records>

あなたのスタイルシートの

  <records>
    <xsl:for-each select="remove($lines, $recordCountIndex)">
      <record>
        <xsl:for-each select="tokenize(., ' ')[position() lt 4]">
          <xsl:element name="item{position()}">
            <xsl:value-of select="."/>
          </xsl:element>
        </xsl:for-each>
      </record>
    </xsl:for-each>
  </records>

position() lt 4実際には、行に 3 つ以上のトークンを含めることができる場合にのみ述語が必要です。

注意として、私は今for-each select="$records[position()]、あなたの投稿で 2 回のような構造を見てきました。その述語 with[position()]はまったく役に立ちませんfor-each select="$records"

于 2012-05-23T14:14:01.670 に答える