1

これに少し引っかかっています。データは次の形式で提供されます (重要でないコンテンツは省略されています)。

<?xml version="1.0" encoding="UTF-8"?>
<Content Type="Statutes">
  <Indexes>
    <!--SNIP-->
    <Index Level="3" HasChildren="0">
      <!--SNIP-->
      <Content>&lt;p&gt; (1)(a)The statutes ... &lt;/p&gt;&lt;p&gt; (b)To ensure public ..: &lt;/p&gt;&lt;p&gt; 
            (I)Shall authorize ...; &lt;/p&gt;&lt;p&gt; (II)May authorize and ...: &lt;/p&gt;&lt;p&gt; (A)Compact disks; 
            &lt;/p&gt;&lt;p&gt; (B)On-line public ...; &lt;/p&gt;&lt;p&gt; (C)Electronic applications for ..; 
            &lt;/p&gt;&lt;p&gt; (D)Electronic books or ... &lt;/p&gt;&lt;p&gt; (E)Other electronic products or formats; 
            &lt;/p&gt;&lt;p&gt; (III)May, pursuant ... &lt;/p&gt;&lt;p&gt; (IV)Recognizes that ... &lt;/p&gt;&lt;p&gt; 
            (2)(a)Any person, ...: &lt;/p&gt;&lt;p&gt; (I)A statement specifying ...; &lt;/p&gt;&lt;p&gt; (II)A statement 
            specifying ...; &lt;/p&gt;&lt;p&gt; (3)A statement 
            specifying ...; &lt;/p&gt;&lt;p&gt; (4)A statement 
            specifying ...; &lt;/p&gt;</Content>
    </Index>
    <!--SNIP-->
  </Indexes>
</Content>

セマンティック階層を含む要素Contentのテキスト値を取得する必要があります。

(1)
 +-(a)
    +-(I)
       +-(A)

...最終的な出力として親子要素関係として XSLT 2.0 変換を介して配置します。

    <?xml version="1.0" encoding="UTF-8"?>
    <law>
       <!--SNIP-->
       <content>
          <section prefix="(1)">
            <section prefix="(a)">The statutes ...
            <section prefix="(b)">To ensure public ..:
              <section prefix="(I)">Shall authorize ...;</section>
              <section prefix="(II)">May authorize and ...:
                <section prefix="(A)">Compact disks;</section>
                <section prefix="(B)">On-line public ...;</section>
                <section prefix="(C)">Electronic applications for ..;</section>
                <section prefix="(D)">Electronic books or ...</section>
                <section prefix="(E)">Other electronic products or formats;</section>
              </section>
              <section prefix="(III)">May, pursuant ...</section>
              <section prefix="(IV)">Recognizes that ...</section>        
            </section>      
          </section>
          <section prefix="(2)">
            <section prefix="(a)">Any person, ...:
              <section prefix="(I)">A statement specifying ...;</section>
              <section prefix="(II)">A statement specifying ...;</section>
            </section>      
          </section>
          <section prefix="(3)">Level 1 node with no children</section>
       </content>
    </law>

コンテンツのテキスト値から HTML エンコードされた P タグの終了をトークン化できましたが、動的に作成された要素を取得して条件付きの子要素を作成する方法の手がかりがありませんでした。

私の XSLT 2.0 スタイルシート:

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

    <xsl:template match="/Content">
        <!-- Work from the lowest index level with no children up -->
        <xsl:apply-templates select=".//Index[@HasChildren=0]"/>
    </xsl:template>  

    <xsl:template match="Index[@HasChildren=0]">
        <law>
            <structure>
                <xsl:apply-templates select="Content"/>
            </structure>
        </law>
    </xsl:template>

    <!-- Template for Content element from originial -->
    <xsl:template match="Content">
        <content>
            <!-- Loop through HTML encoded P tag endings -->
            <xsl:for-each select="tokenize(.,'&lt;/p&gt;')">

                <!-- Set Token to a variable and remove P opening tags -->
                <xsl:variable name="sectionText">
                    <xsl:value-of select="normalize-space(replace(current(),'&lt;p&gt;',''))"/>  
                </xsl:variable>    

                <!-- Output -->
                <xsl:if test="string-length($sectionText)!=0">
                    <section>
                        <!-- Set the section element's prefix attribute (if exists) -->
                        <xsl:analyze-string select="$sectionText" regex="^(\(([\w]+)\)){{1,3}}">
                            <xsl:matching-substring >
                                <xsl:attribute name="prefix" select="." />
                            </xsl:matching-substring>
                        </xsl:analyze-string>

                        <!-- Set the section element's value -->
                        <xsl:value-of select="$sectionText"/>
                    </section>
                </xsl:if>

            </xsl:for-each>
        </content>
    </xsl:template>
</xsl:stylesheet> 

...これで私はここまで来ました-セクション要素内にセマンティック階層がありません:

<?xml version="1.0" encoding="UTF-8"?>
<law>
   <structure>
      <content>
         <section prefix="(1)(a)">(1)(a)The statutes ...</section>
         <section prefix="(b)">(b)To ensure public ..:</section>
         <section prefix="(I)">(I)Shall authorize ...;</section>
         <section prefix="(II)">(II)May authorize and ...:</section>
         <section prefix="(A)">(A)Compact disks;</section>
         <section prefix="(B)">(B)On-line public ...;</section>
         <section prefix="(C)">(C)Electronic applications for ..;</section>
         <section prefix="(D)">(D)Electronic books or ...</section>
         <section prefix="(E)">(E)Other electronic products or formats;</section>
         <section prefix="(III)">(III)May, pursuant ...</section>
         <section prefix="(IV)">(IV)Recognizes that ...</section>
         <section prefix="(2)(a)">(2)(a)Any person, ...:</section>
         <section prefix="(I)">(I)A statement specifying ...;</section>
         <section prefix="(II)">(II)A statement specifying ...;</section>
         <section prefix="(3)">(3)Level 1 section with no children ...;</section>
      </content>
   </structure>
</law>

Section要素は、終了 P タグをトークン化することによって XSLT 2.0 スタイルシートによって動的に作成されるため、 prefix属性 を介して既知のセマンティック階層を使用して動的に親子関係を構築するにはどうすればよいでしょうか?

他のプログラミング言語の経験から、ネストのための前のプレフィックスに対するプレフィックスのトークン化とロジックに基づく再帰の方向に私は導かれます - v2.0 での限られた XSLT 知識 (v1. 0 ほぼ 10 年以上前)。外部の Python スクリプトを使用して解析するだけで済むことはわかっていますが、保守性のために XSLT 2.0 スタイルシート ソリューションに固執しようとしています。

正しい軌道や解決策にたどり着くために、どんな助けでも大歓迎です。

4

2 に答える 2

2

次のような要素を含む中間出力を作成するために、問題の 1 つのトリッキーなフェーズに取り組みました。

<section prefix="(1)(a)">text</section>

私の次のステップは、レベル番号を計算することなので、次のようになります。

<section level="1" prefix="(1)(a)">text</section>

レベル番号の計算は、プレフィックスがいくつかの正規表現のどれに一致するかを確認するだけの問題です: (1) レベル 1、(b) レベル 2 など。

レベル番号を取得したら、このペーパーで説明されているように、再帰的な位置グループ化を使用できます: http://www.saxonica.com/papers/ideadb-1.1/mhk-paper.xml

于 2013-10-29T09:11:50.600 に答える
1

私はこれで少し遊んで、次のスタイルシートを思いつきました:

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

    <xsl:include href="htmlparse.xml"/>

    <xsl:param name="patterns" as="element(pattern)*" xmlns="">
      <pattern value="^\s*(\([0-9]+\))" group="1" next="1"/>
      <pattern value="^\s*(\([0-9]+\))?\s*(\([a-z]\))" group="2" next="0"/>
      <pattern value="^\s*(\(*(I|II|III|IV|V|VI|VII|VIII|IX|X|XI|XII|XIII)\))" group="1" next="0"/>
      <pattern value="^\s*(\([A-Z]?\))" group="1" next="0"/>
    </xsl:param>

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

    <xsl:function name="mf:group" as="element(section)*">
      <xsl:param name="paragraphs" as="element(p)*"/>
      <xsl:param name="patterns" as="element(pattern)*"/>
      <xsl:variable name="pattern1" as="element(pattern)?" select="$patterns[1]"/>
      <xsl:for-each-group select="$paragraphs" group-starting-with="p[matches(., $pattern1/@value)]">
        <xsl:variable name="prefix" as="xs:string?">
          <xsl:analyze-string select="." regex="{$pattern1/@value}">
            <xsl:matching-substring>
              <xsl:sequence select="string(regex-group(xs:integer($pattern1/@group)))"/>
            </xsl:matching-substring>
          </xsl:analyze-string>
        </xsl:variable>
        <section prefix="{$prefix}">
          <xsl:choose>
            <xsl:when test="xs:boolean(xs:integer($pattern1/@next))">
              <xsl:sequence select="mf:group(current-group(), $patterns[position() gt 1])"/>
            </xsl:when>
            <xsl:otherwise>
              <xsl:apply-templates select="node()">
                <xsl:with-param name="pattern" as="element(pattern)" select="$pattern1" tunnel="yes"/>
              </xsl:apply-templates>
              <xsl:sequence select="mf:group(current-group() except ., $patterns[position() gt 1])"/>
            </xsl:otherwise>
          </xsl:choose>
        </section>
      </xsl:for-each-group>
    </xsl:function>

    <xsl:template match="/Content">
        <!-- Work from the lowest index level with no children up -->
        <xsl:apply-templates select=".//Index[@HasChildren=0]"/>
    </xsl:template>  

    <xsl:template match="Index[@HasChildren=0]">
        <law>
            <structure>
                <xsl:apply-templates select="Content"/>
            </structure>
        </law>
    </xsl:template>

    <!-- Template for Content element from originial -->
    <xsl:template match="Content">

        <content>
            <xsl:sequence select="mf:group(d:htmlparse(., '', true())/*, $patterns)"/>
        </content>
    </xsl:template>

    <xsl:template match="p/text()[1]">
      <xsl:param name="pattern" as="element(pattern)" tunnel="yes"/>
      <xsl:value-of select="replace(., $pattern/@value, '')"/>
    </xsl:template>
</xsl:stylesheet> 

XSLT 2.0 で記述された HTML タグ スープ パーサーであるhttp://web-xslt.googlecode.com/svn/trunk/htmlparse/htmlparse.xslを使用して、エスケープされた HTML フラグメント マークアップをノードに解析し、ノードを使用してグループ化します。スタイルシートの関数mf:group。グループ化は、パラメーターとして渡される一連の正規表現パターンによって行われます。

入力サンプルにSaxon 9.5のスタイルシートを適用すると、結果が得られます

<law>
   <structure>
      <content>
         <section prefix="(1)">
            <section prefix="(a)">The statutes ... </section>
            <section prefix="(b)">To ensure public ..: <section prefix="(I)">Shall authorize ...; </section>
               <section prefix="(II)">May authorize and ...: <section prefix="(A)">Compact disks;
            </section>
                  <section prefix="(B)">On-line public ...; </section>
                  <section prefix="(C)">Electronic applications for ..;
            </section>
                  <section prefix="(D)">Electronic books or ... </section>
                  <section prefix="(E)">Other electronic products or formats;
            </section>
               </section>
               <section prefix="(III)">May, pursuant ... </section>
               <section prefix="(IV)">Recognizes that ... </section>
            </section>
         </section>
         <section prefix="(2)">
            <section prefix="(a)">Any person, ...: <section prefix="(I)">A statement specifying ...; </section>
               <section prefix="(II)">A statement
            specifying ...; </section>
            </section>
         </section>
      </content>
   </structure>
</law>

現在、XIII を含む数字のみをリストしているため、13 (XIII) セクションを超える可能性がある場合は、ローマ数字の正規表現パターンを使用してパラメーターを編集し、より多くの数字をリストする必要があります。

コメントと編集された入力サンプルに基づいて、スタイルシートを少し調整しました。

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

    <xsl:include href="htmlparse.xml"/>

    <xsl:param name="patterns" as="element(pattern)*" xmlns="">
      <pattern value="^\s*(\([0-9]+\))" group="1" next="1"/>
      <pattern value="^\s*(\([0-9]+\))?\s*(\([a-z]\))" group="2" next="0"/>
      <pattern value="^\s*(\(*(I|II|III|IV|V|VI|VII|VIII|IX|X|XI|XII|XIII)\))" group="1" next="0"/>
      <pattern value="^\s*(\([A-Z]?\))" group="1" next="0"/>
    </xsl:param>

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

    <xsl:function name="mf:group" as="element(section)*">
      <xsl:param name="paragraphs" as="element(p)*"/>
      <xsl:param name="patterns" as="element(pattern)*"/>
      <xsl:variable name="pattern1" as="element(pattern)?" select="$patterns[1]"/>
      <xsl:for-each-group select="$paragraphs" group-starting-with="p[matches(., $pattern1/@value)]">
        <xsl:variable name="prefix" as="xs:string?">
          <xsl:analyze-string select="." regex="{$pattern1/@value}">
            <xsl:matching-substring>
              <xsl:sequence select="string(regex-group(xs:integer($pattern1/@group)))"/>
            </xsl:matching-substring>
          </xsl:analyze-string>
        </xsl:variable>
        <section prefix="{$prefix}">
          <xsl:choose>
            <xsl:when test="xs:boolean(xs:integer($pattern1/@next)) and matches(., $patterns[2]/@value)">
              <xsl:sequence select="mf:group(current-group(), $patterns[position() gt 1])"/>
            </xsl:when>
            <xsl:otherwise>
              <xsl:apply-templates select="node()">
                <xsl:with-param name="pattern" as="element(pattern)" select="$pattern1" tunnel="yes"/>
              </xsl:apply-templates>
              <xsl:sequence select="mf:group(current-group() except ., $patterns[position() gt 1])"/>
            </xsl:otherwise>
          </xsl:choose>
        </section>
      </xsl:for-each-group>
    </xsl:function>

    <xsl:template match="/Content">
        <!-- Work from the lowest index level with no children up -->
        <xsl:apply-templates select=".//Index[@HasChildren=0]"/>
    </xsl:template>  

    <xsl:template match="Index[@HasChildren=0]">
        <law>
            <structure>
                <xsl:apply-templates select="Content"/>
            </structure>
        </law>
    </xsl:template>

    <!-- Template for Content element from originial -->
    <xsl:template match="Content">

        <content>
            <xsl:sequence select="mf:group(d:htmlparse(., '', true())/*, $patterns)"/>
        </content>
    </xsl:template>

    <xsl:template match="p/text()[1]">
      <xsl:param name="pattern" as="element(pattern)" tunnel="yes"/>
      <xsl:value-of select="replace(., $pattern/@value, '')"/>
    </xsl:template>
</xsl:stylesheet> 

今、それは変形します

<?xml version="1.0" encoding="UTF-8"?>
<Content Type="Statutes">
  <Indexes>
    <!--SNIP-->
    <Index Level="3" HasChildren="0">
      <!--SNIP-->
      <Content>&lt;p&gt; (1)(a)The statutes ... &lt;/p&gt;&lt;p&gt; (b)To ensure public ..: &lt;/p&gt;&lt;p&gt; 
            (I)Shall authorize ...; &lt;/p&gt;&lt;p&gt; (II)May authorize and ...: &lt;/p&gt;&lt;p&gt; (A)Compact disks; 
            &lt;/p&gt;&lt;p&gt; (B)On-line public ...; &lt;/p&gt;&lt;p&gt; (C)Electronic applications for ..; 
            &lt;/p&gt;&lt;p&gt; (D)Electronic books or ... &lt;/p&gt;&lt;p&gt; (E)Other electronic products or formats; 
            &lt;/p&gt;&lt;p&gt; (III)May, pursuant ... &lt;/p&gt;&lt;p&gt; (IV)Recognizes that ... &lt;/p&gt;&lt;p&gt; 
            (2)(a)Any person, ...: &lt;/p&gt;&lt;p&gt; (I)A statement specifying ...; &lt;/p&gt;&lt;p&gt; (II)A statement 
            specifying ...; &lt;/p&gt;&lt;p&gt; (3)A statement 
            specifying ...; &lt;/p&gt;&lt;p&gt; (4)A statement 
            specifying ...; &lt;/p&gt;</Content>
    </Index>
    <!--SNIP-->
  </Indexes>
</Content>

<law>
   <structure>
      <content>
         <section prefix="(1)">
            <section prefix="(a)">The statutes ... </section>
            <section prefix="(b)">To ensure public ..: <section prefix="(I)">Shall authorize ...; </section>
               <section prefix="(II)">May authorize and ...: <section prefix="(A)">Compact disks;
            </section>
                  <section prefix="(B)">On-line public ...; </section>
                  <section prefix="(C)">Electronic applications for ..;
            </section>
                  <section prefix="(D)">Electronic books or ... </section>
                  <section prefix="(E)">Other electronic products or formats;
            </section>
               </section>
               <section prefix="(III)">May, pursuant ... </section>
               <section prefix="(IV)">Recognizes that ... </section>
            </section>
         </section>
         <section prefix="(2)">
            <section prefix="(a)">Any person, ...: <section prefix="(I)">A statement specifying ...; </section>
               <section prefix="(II)">A statement
            specifying ...; </section>
            </section>
         </section>
         <section prefix="(3)">A statement
            specifying ...; </section>
         <section prefix="(4)">A statement
            specifying ...; </section>
      </content>
   </structure>
</law>
于 2013-10-30T14:46:33.807 に答える