1

ノードを前の兄弟の子に移動しようとしていますが、すべてが同じレベルにあるという事実により、ノードは少し注意が必要です。

私の入力のイラスト:

<dl>
   <dlentry>
      <dt> Title 1 </dt>
      <dd> Title 1's definition </dd>
      <dt> Title 2 </dt>
      <dd> Title 2's definition </dd> 
      <dt> Title 3 </dt>
      <dd> Title 3's definition </dd>
   </dlentry>
</dl> 
<p> part of title 3's definition </p>
<p> another part of title 3's definition </p>

私がやろうとしているのは、これら2つの要素を下部に配置し、それらのテキストを「タイトル3」の定義の一部であるため、最後の要素のテキスト<p>の最後に連結することです。<dd><dlentry>

必要な出力:

<dl>
   <dlentry>
      <dt> Title 1 </dt>
      <dd> Title 1's definition </dd>
      <dt> Title 2 </dt>
      <dd> Title 2's definition </dd> 
      <dt> Title 3 </dt>
      <dd> Title 3's definition part of title 3's definition another part of title 3's  definition </dd>
   </dlentry>
</dl>

私が扱っているもう1つの問題は、ソースドキュメントのXHTMLがいかに悪いかということです。これらの<p>要素のテキストに対して正規表現を一致させて、ドキュメント内の他の場所にヒットしないようにする必要があります。

最初<p>のテキストを希望どおりに正常に挿入できましたが、正規表現の一致を実行して2番目のテキストを取得できるように、テキストを機能させるのに問題があります。

要素のテキストも目的の場所に配置します。

これは、XSLT2.0を使用したスタイルシートのコードフラグメントです。

<xsl:analyze-string select="."
      regex="my regex expression here">

<xsl:template match="dlentry">

  <xsl:matching-substring>
    <dlentry>
     ** <xsl:copy-of select="node()[ position() lt last()]"/>
         <dd>
           <xsl:copy-of select="node()[last()]/text()" />
           <xsl:copy-of select=" parent::node()/following-sibling::node()[1]/text()"/>
         </dd>
    </dlentry>
  </xsl:matching-substring>

  <xsl:non-matching-substring>
      <xsl:value-of select=".">
  </xsl:non-matching-substring>

</xsl:template>

<xsl:template match="p[preceding-sibling::node()[1][self::node()[name(.)='dl']]]" />
<xsl:template match="p[preceding-sibling::node()[2][self::node()[name(.)='dl']]]" />

**アスタリスクが付いたコード行で、Saxonは「Axisstep child :: node()はここでは使用できません:コンテキストアイテムはアトミック値です」というエラーをスローします。私はanalyze-stringに精通していませんが、analyze-stringの外部でテンプレート内でcopy-of selectを実行すると、正常に実行されます。

この質問はちょっと長かったので申し訳ありませんが、私はこれまでに持っていたすべてを共有したいと思いました。

前もって感謝します。

4

2 に答える 2

2

この短くて単純なXSLT1.0(そしてもちろんXSLT 2.0でもあります):

<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:key name="kFollowing" match="p" use="generate-id(preceding-sibling::dl[1])"/>

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

 <xsl:template match="dlentry/dd[last()]">
  <dd>
   <xsl:apply-templates select=
    "(.|key('kFollowing', generate-id(ancestor::dl[1])))/text()"/>
  </dd>
 </xsl:template>
 <xsl:template match="p"/>
</xsl:stylesheet>

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

<html>
    <dl>
        <dlentry>
            <dt> Title 1 </dt>
            <dd> Title 1's definition </dd>
            <dt> Title 2 </dt>
            <dd> Title 2's definition </dd>
            <dt> Title 3 </dt>
            <dd> Title 3's definition </dd>
        </dlentry>
    </dl>
    <p> part of title 3's definition </p>
    <p> another part of title 3's definition </p>
</html>

必要な正しい結果を生成します。

<html>
   <dl>
      <dlentry>
         <dt> Title 1 </dt>
         <dd> Title 1's definition </dd>
         <dt> Title 2 </dt>
         <dd> Title 2's definition </dd>
         <dt> Title 3 </dt>
         <dd> Title 3's definition  part of title 3's definition  another part of title 3's definition </dd>
      </dlentry>
   </dl>
</html>
于 2012-09-20T03:53:00.870 に答える
1

効率についてはわかりませんが、xslに従うと、要求された出力が生成されます。

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="xml" indent="yes"/>
 <xsl:template match="/doc">
  <xsl:for-each select="dl">
   <dl>
    <xsl:for-each select="dlentry">
      <xsl:apply-templates select="dt|dd"/>
    </xsl:for-each>
   </dl>
  </xsl:for-each>
 </xsl:template>

 <xsl:template match="dt">
  <dt><xsl:value-of select="."/></dt>
 </xsl:template>

 <xsl:template match="dd">
  <dd>
    <xsl:value-of select="."/>
    <!-- Check if this is the last element (= no dd/dd after) -->
    <xsl:if test="not(following-sibling::*)">
     <!-- Select dl's next sibling, if it's a <p> -->
     <xsl:for-each select="../../following-sibling::*[1][name() = 'p']">
      <!-- Call recursive template -->
      <xsl:call-template name="concat"/>
     </xsl:for-each>
    </xsl:if>
  </dd>
 </xsl:template>

 <xsl:template name="concat">
   <xsl:value-of select="."/>
   <!-- Select p's next sibling, if it's a <p> -->
   <xsl:for-each select="following-sibling::*[1][name() = 'p']">
    <!-- Call recursive template -->
    <xsl:call-template name="concat"/>
   </xsl:for-each>
 </xsl:template>
</xsl:stylesheet>

そして、これが私がそれをテストした入力です:

<doc>
 <dl>
   <dlentry>
      <dt> Title 1 </dt>
      <dd> Title 1's definition </dd>
      <dt> Title 2 </dt>
      <dd> Title 2's definition </dd>
      <dt> Title 3 </dt>
      <dd> Title 3's definition </dd>
   </dlentry>
 </dl>
 <p> part of title 3's definition </p>
 <p> another part of title 3's definition </p>
</doc>
于 2012-09-19T21:18:19.907 に答える