2

到底是什么?

我们需要创建一个 xslt 文件,它将执行以下操作。整个故事是关于立法的。想想立法修改发生了什么。你有一个旧的法律 X 和立法者带来了一个新的法律 Y,它有参考法律 X 的修改。修改可以替换法律的任何类型的子部分(部分、文章、段落等)。


第十条

第1条

  1. 这里的东西真的很老
  2. 等等等等等等

第 2 条 [....]


法律 Y

第1条

  1. 等等等等等等

第二条

  1. 将法律 Y 中第 1 条的第 1 段替换为:“新鲜和令人敬畏的东西”。

你真正想知道什么?


法律 X'

第1条

  1. 一些新鲜和令人敬畏的东西
  2. 等等等等等等

第 2 条 [....]


让我们进入 XML 立法世界

我们有这样的 XML 文件 X

<Legislation DocumentURI="X">
<Metadata>[...]</Metadata>
<Introduction>[...]</Introduction>
<Body>
<Article DocumentURI="X/article/1">
<P DocumentURI="X/article/1/paragraph/1">
   <P2 DocumentURI="X/article/1/paragraph/1/passage/1">
            <Text>SOMETHING REALLY OLD HERE</Text>
   </P2>
</P>
<P DocumentURI="X/article/1/paragraph/2">
   <P2 DocumentURI="X/article/1/paragraph/2/passage/1">
            <Text>blahblahblah</Text>
   </P2>
</P>
</Article>
</Body>
</Legislation>

我们有这样的 XML 文件 Y

<Legislation DocumentURI="Y">
<Metadata>[...]</Metadata>
<Introduction>[...]</Introduction>
<Body>
<Article DocumentURI="Y/article/1">
<P DocumentURI="Y/article/1/paragraph/1">
   <P2 DocumentURI="Y/article/1/paragraph/1/passage/1">
            <Text>blahblahblah</Text>
   </P2>
</P>
</Article>
<Article DocumentURI="Y/article/2">
<P DocumentURI="Y/article/2/paragraph/1">
   <P2 DocumentURI="Y/article/2/paragraph/1/passage/1">
            <Text>Replace the 1st paragraph of the 1st article in Law Y as:</Text>
   </P2>
   <Modification DocumentURI="Y/modification/1">
     <P2 URI="X/article/1/paragraph/1/passage/1">
        <Text>SOMETHING FRESH ANS AWESOME</Text>
     </P2>
   </Modification>
</P>
</Article>
</Body>
</Legislation>

我们将产生 X':

<Legislation DocumentURI="X">
<Metadata>[...]</Metadata>
<Introduction>[...]</Introduction>
<Body>
<Article DocumentURI="X/article/1">
<P DocumentURI="X/article/1/paragraph/1">
   <P2 DocumentURI="X/article/1/paragraph/1/passage/1">
            <Text>SOMETHING FRESH AND AWESOME</Text>
   </P2>
</P>
<P DocumentURI="X/article/1/paragraph/2">
   <P2 DocumentURI="X/article/1/paragraph/2/passage/1">
            <Text>blahblahblah</Text>
   </P2>
</P>
</Article>
</Body>
</Legislation>

提示: <Modification>内容可以是法律的任何一种子部分。可能是像上面这样的单个 XML 元素,也可能是像整篇文章一样的整个嵌套节点!

TIP2:谁告诉你<Modification>同一个元素只出现一次?也许在 2012 年,Y 法修改了特定部分,然后在 2013 年,新的 Z 法以不同的方式修改了已经修改的部分或该部分的子部分!

提示3:谁告诉你<Modification>指的是一个元素,它已经在文件 X 中了?也许法律 Y 在旧的法律 X 中添加了一个新部分!

我们怎么知道修改在哪里?

  1. 我们知道它们的 DocumentURI 属性值。
  2. 我们知道它们所在的 XML 文件。

在使用 XSLT 之前,会调用一个操作(findmodifications)。该操作使用来自 URL 的通配符 (*),表示法律的 id,并在 rdfstore 中搜索修改。最后我们设置了一个叫做修改的请求参数,来返回结果。

修改的参数具有以下结构:

modification[0][0] = PD201210.xml  
modification[0][1] = http://localhost:8888/GRLegislation/pd/2012/10/modification/1  
modification[1][0] = PD201210.xml  
modification[1][1] = http://localhost:8888/GRLegislation/pd/2012/10/modification/2  
.  
.  
.

毕竟您想对修改后的 XML 内容 X' 做什么?

我将 Apache Cocoon 框架用于我的 Web 应用程序项目,因此我的站点地图中有一个特定的管道,它调用一个操作以查找修改的位置,然后获取 X 文件,执行 xslt 转换并将其序列化为 HTML。

<map:pipeline id="law-updated">
      <map:match pattern="pd/*/updated">
        <map:act type="findmodifications">      
        </map:act>
        <map:generate src="{1}.xml" type="file"/>
        <map:transform src="legislation_updated.xslt" type="xslt"/>
        <map:serialize type="xhtml"/>
      </map:match>
</map:pipeline>

我的用于 HTML 转换的 XSLT 模板在这里:

<xsl:template match="/">
    <html>
        <head>
        </head>
        <body>
            <div id="wrapper">
                <div id="header">
                        ............
                </div>
                <div id="content">
                    <div id="content_column">
                        <div class="button" >
                            <a>
                                <xsl:attribute name="href">
                                    <xsl:value-of select="Legislation/Metadata/dc:identifier"/>/data.rdf
                                </xsl:attribute>RDF</a>
                        </div><br/><br/>
                        <div class="button" >
                            <a style="color: #fff;">
                                <xsl:attribute name="href">
                                    <xsl:value-of select="Legislation/Metadata/dc:identifier"/>/data.pdf
                                </xsl:attribute>PDF</a>
                        </div><br/>

                    </div>
                    <div id="content_body">
                        <div id="content_text">
                          <div id="content_bar">
                                 <ul>
                                    <li style="font-size: 16px; font-weight: bold; float:left; padding-right:2em;">
                                        <a><xsl:attribute name="href">
                                            <xsl:value-of select="Legislation/Metadata/dc:identifier"/>/contents
                                        </xsl:attribute>Περιεχόμενα</a>
                                    </li>
                                    <li style="font-size: 16px; font-weight: bold; float:left; padding-right:2em;">
                                        <a><xsl:attribute name="href">
                                            <xsl:value-of select="Legislation/Metadata/dc:identifier"/>
                                        </xsl:attribute>Κείμενο</a>
                                    </li>
                                    <li style="font-size: 16px; font-weight: bold; float:left; padding-right:2em;">
                                        <a><xsl:attribute name="href">
                                            <xsl:value-of select="Legislation/Metadata/dc:identifier"/>/timeline
                                        </xsl:attribute>Χρονολόγιο</a>
                                    </li>
                                    <li style="font-size: 16px; font-weight: bold; float:left; padding-right:2em;">
                                        <a><xsl:attribute name="href">
                                            <xsl:value-of select="Legislation/Metadata/dc:identifier"/>/citations
                                        </xsl:attribute>Παραπομπές</a>
                                    </li>
                                </ul>
                                </div>
                                <br/>
                                <br/>
                        <table border="0">
                        <tr><td>ΦΕΚ:&#160;</td> 
                            <td><xsl:value-of select="Legislation/Metadata/diavgeia:fek/issue"/>
                        / <xsl:value-of select="Legislation/Metadata/diavgeia:fek/year"/>
                        / <xsl:value-of select="Legislation/Metadata/diavgeia:fek/fekNumber"/>
                        </td></tr>
                        <tr>
                            <td>ΚΩΔΙΚΟΣ ΑΠΟΦΑΣΗΣ:&#160;</td>
                            <td> <xsl:value-of select="Legislation/Metadata/diavgeia:decisionType/diavgeia:label"/>
                            &#160; <xsl:value-of select="Legislation/Metadata/Year"/>
                            / <xsl:value-of select="Legislation/Metadata/Number"/>
                            </td>
                        </tr>
                        <tr>
                            <td>ΗΜΕΡΟΜΗΝΙΑ ΕΚΔΟΣΗΣ:&#160;</td> 
                            <td>
                                <xsl:value-of select="Legislation/Metadata/dc:created"/>

                            </td>

                        </tr>
                        <tr>
                            <td>ΥΠΟΓΡΑΦΗ:&#160;</td> 
                            <td>
                                <xsl:for-each select="Legislation/Metadata/diavgeia:signer">
                                <a><xsl:attribute name="href">http://localhost:8888/GRLegislation/signer/<xsl:value-of select="@uid"/></xsl:attribute>
                                <xsl:value-of select="diavgeia:firstName"/>&#160;
                                <xsl:value-of select="diavgeia:lastName"/>
                                </a>
                                <xsl:choose>
                                <xsl:when test="position() != last()">,&#160;</xsl:when>
                                </xsl:choose>
                                </xsl:for-each>
                            </td>

                        </tr>
                         <tr>
                            <td>ΣΧΕΤΙΚΑ ΜΕ:&#160;</td> 
                            <td>
                                <xsl:for-each select="Legislation/Metadata/diavgeia:tag">
                                <xsl:value-of select="diavgeia:label"/>
                                <xsl:choose>
                                <xsl:when test="position() != last()">,&#160;</xsl:when>
                                </xsl:choose>
                               </xsl:for-each>
                            </td>

                        </tr>
                        </table>
                        <br/>
                        <h4>
                            <xsl:value-of select="Legislation/Metadata/dc:title"/>
                        </h4>

                                                 <br/>
                                                 <xsl:for-each select="Legislation/Body/Article">
                                                    <div><xsl:attribute name="id"><xsl:value-of select="@id"/></xsl:attribute>
                                                    <p>
                                                        <h5>Άρθρο
                                                            <xsl:value-of select="Number"/>
                                                        </h5>
                                                        <xsl:if test="Title">
                                                        <h6>
                                                            <xsl:value-of select="Title"/>
                                                         </h6>
                                                         </xsl:if>
                                                        <br/>
                                                        <ol>
                                                        <xsl:for-each select="P">
                                                            <div><xsl:attribute name="id">
                                                                <xsl:value-of select="@DocumentURI"/>
                                                                </xsl:attribute>
                                                            <li>
                                                             <xsl:for-each select="P2">
                                                                 <xsl:value-of select="Text"/>&#160;
                                                             </xsl:for-each>
                                                             <xsl:for-each select="List">
                                                                 <ol style="list-style-type:lower-greek">
                                                                 <xsl:for-each select="Case">
                                                                     <li>
                                                                         <xsl:value-of select="Text"/>
                                                                     </li>
                                                                 </xsl:for-each>
                                                                 </ol>
                                                             </xsl:for-each>
                                                             <xsl:for-each select="Modification">

                                                                <div id="modification" >
                                                                 <xsl:if test="P">
                                                                    <ol>
                                                                    <xsl:for-each select="P">
                                                                        <li>
                                                                            <xsl:attribute name="value">
                                                                            <xsl:value-of select="Number"/>
                                                                            </xsl:attribute>
                                                                         <xsl:for-each select="P2">
                                                                             <xsl:value-of select="Text"/>&#160;
                                                                         </xsl:for-each>
                                                                         <xsl:for-each select="List">
                                                                             <ol style="list-style-type:lower-greek">
                                                                             <xsl:for-each select="Case">
                                                                                 <li>
                                                                                     <xsl:value-of select="Text"/>
                                                                                 </li>
                                                                             </xsl:for-each>
                                                                             </ol>
                                                                         </xsl:for-each>
                                                                        </li> 
                                                                    </xsl:for-each>
                                                                    </ol>
                                                                 </xsl:if>
                                                                 <xsl:if test="P2">
                                                                        <xsl:for-each select="P2">
                                                                        <xsl:value-of select="Text"/>&#160;
                                                                        </xsl:for-each>
                                                                 </xsl:if>
                                                                 <xsl:if test="Case">
                                                                     <ol>   
                                                                    <xsl:for-each select="Case">
                                                                     <li><xsl:attribute name="value">
                                                                            <xsl:value-of select="Value"/>
                                                                            </xsl:attribute>
                                                                         <xsl:value-of select="Text"/>
                                                                     </li>
                                                                    </xsl:for-each>
                                                                     </ol>
                                                                 </xsl:if>
                                                                </div>
                                                             </xsl:for-each>
                                                            </li> 
                                                            </div>                                                           
                                                        </xsl:for-each>
                                                        </ol>
                                                    </p>
                                                    </div>
                                                 </xsl:for-each>
                    </div>
                    </div>
                </div>
        </body>
    </html>
  </xsl:template>

如果您需要额外的信息,请询问。一个真正的 XML X 文件在这里。一个对 X 进行了修改的真正的 XML Y 文件在这里修改后的XML在这里会是这样提前谢谢!

修改类型:

  1. 替换一个节点,如修改真实 XML 文件 Y 的 2、3、4。
  2. 添加一个节点,如真实 XML 文件 Z 的修改 1。
  3. 删除一个节点。假设删除的修改将具有空节点的结构。喜欢<Modification DocumentURI=""><P2 DocumentURI=""></P2></Modification>
4

2 回答 2

1

这是一个样式表,可能会让你开始。

它旨在将一个文档(“旧状态”)与另一个文档(“新状态”)合并。

  • 它不会触及文档标题/元数据。这是取自“旧状态”。如果你想使用别的东西,写一个适当的<xsl:template match="Metadata">等。
  • 它贯穿“旧状态”的所有节点。如果<Modification>在“新状态”中存在引用任何“旧状态”节点的 a,则复制修改的内容。
  • 否则,将复制旧状态。
  • 它假定来自“新状态”的所有添加都附加到已经存在的内容中。因为否则,它们只会是变化,对吧?
  • 它是基于参数的。如果您想应用多项修改,请逐步进行,使用上一次运行的输出作为下一次运行的输入。

我已经使用真实的 XML 文件和您的示例进行了测试。

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

  <xsl:param name="modificationsDoc" select="''" />

  <xsl:variable name="existingURIs" select="//@DocumentURI" />
  <xsl:variable name="mods" select="document($modificationsDoc)//Modification/*" />

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

  <!-- only elements with DocumentURI can be target of modifications -->
  <xsl:template match="*[@DocumentURI]">
    <xsl:variable name="currURI" select="@DocumentURI" />
    <xsl:variable name="matchingMod" select="$mods[@DocumentURI = $currURI]" />

    <!-- replacements and deletions -->
    <xsl:choose>
      <xsl:when test="$matchingMod">
        <!-- no output for empty modifications (they are deletions) -->
        <xsl:if test="$matchingMod[*]">
          <xsl:copy-of select="$matchingMod" />
        </xsl:if>
      </xsl:when>
      <xsl:otherwise>
        <xsl:call-template name="identity" />
      </xsl:otherwise>
    </xsl:choose>

    <!-- additions -->
    <xsl:variable name="siblingURI">
      <xsl:call-template name="substring-before-last">
        <xsl:with-param name="string1" select="$currURI" />
        <xsl:with-param name="string2" select="'/'" />
      </xsl:call-template>
      <xsl:text>/</xsl:text>
    </xsl:variable>
    <xsl:copy-of select="$mods[
      number(substring-after(@DocumentURI, $siblingURI)) &gt; 0
      and not(@DocumentURI = $existingURIs)
    ]" />
  </xsl:template>

  <xsl:template name="substring-before-last">
    <xsl:param name="string1" select="''" />
    <xsl:param name="string2" select="''" />

    <xsl:if test="$string1 != '' and $string2 != ''">
      <xsl:variable name="head" select="substring-before($string1, $string2)" />
      <xsl:variable name="tail" select="substring-after($string1, $string2)" />
      <xsl:value-of select="$head" />
      <xsl:if test="contains($tail, $string2)">
        <xsl:value-of select="$string2" />
        <xsl:call-template name="substring-before-last">
          <xsl:with-param name="string1" select="$tail" />
          <xsl:with-param name="string2" select="$string2" />
        </xsl:call-template>
      </xsl:if>
    </xsl:if>
  </xsl:template>

</xsl:stylesheet>

使用您的示例 XML,输出是所需的:

<Legislation DocumentURI="X">
  <Metadata>[...]</Metadata>
  <Introduction>[...]</Introduction>
  <Body>
    <Article DocumentURI="X/article/1">
      <P DocumentURI="X/article/1/paragraph/1">
        <P2 DocumentURI="X/article/1/paragraph/1/passage/1">
          <Text>SOMETHING FRESH ANS AWESOME</Text>
        </P2>
      </P>
      <P DocumentURI="X/article/1/paragraph/2">
        <P2 DocumentURI="X/article/1/paragraph/2/passage/1">
          <Text>blahblahblah</Text>
        </P2>
      </P>
    </Article>
  </Body>
</Legislation>

笔记:

于 2014-01-22T19:44:39.130 回答
1

几天后,我在问题的最后部分找到了完全偶然的解决方案。我们有 2 个不同的 XSLT 样式表:

  • 一个用于 HTML 表示(参见上面的问题),以及
  • 上面的样式表(见答案)来自Tomalak,它处理修改

正如我提到的,我们必须调整 X XML 文件中的修改,然后在 HTML 中发布修改后的 X'。因此 Apache Cocoon 提供了实现这两个步骤的机会,如下所示:

<map:pipeline id="law-updated">
      <map:match pattern="pd/*/updated">
        <map:act type="findmodifications">      
        </map:act>
        <map:generate src="{1}.xml" type="file"/>
        <!-- Tomalak stylesheet -->
        <map:transform src="legislation_updated.xslt" type="xslt"/>
        <!-- HTML stylesheet -->
        <map:transform src="html.xslt" type="xslt"/>
        <map:serialize type="xhtml"/>
      </map:match>
</map:pipeline>

就这么简单,但文档中的任何地方都没有提到它。

剩余问题:在使用 XSLT 之前,调用了一个操作(findmodifications)。该操作使用来自 URL 的通配符 (*),表示法律的 id,并在 rdfstore 中搜索修改。最后我们设置了一个叫做修改的请求参数,来返回结果。

在 Tomalak 的样式表中,修改是内联的(参见前 5 行)。我们要使用请求参数。

修改的参数具有以下结构:

modification[0][0] = PD201210.xml  
modification[0][1] = http://localhost:8888/GRLegislation/pd/2012/10/modification/1  
modification[1][0] = PD201210.xml  
modification[1][1] = http://localhost:8888/GRLegislation/pd/2012/10/modification/2  
.  
.  
.
于 2014-01-29T13:31:23.407 回答