2016-04-21 50 views
1

我在xml文档中有一组兄弟元素需要用XSLT处理到表中,实际上我使用Apache FOP将其转换为pdf。需要在遇到两种类型的元素之一时创建表行。该行中的单元格由导致在第一个单元格中创建该行的元素以及后续单元格中的后续兄弟元素组成,直到导致创建行的下一个元素。下面是一些示例性的XML,以更好地解释:如何使用XPath和XSLT处理一组兄弟节点并基于两个兄弟处理特定的兄弟姐妹子集

<pre class="prettyprint"><code class="language-xml"> 
     <reqpers> 
      <person man="Four"/> 

      <person man="A" id="pers_a"/> 
      <perscat category="Recovery Supervisor"/> 

      <person man="B" id="pers_b"/> 
      <perscat category="Ground Personnel"/> 

      <asrequir/> 
      <perscat category="As Required Category"/> 
      <trade>Bill Collector</trade> 

      <person man="C" id="pers_c"/> 
      <perscat category="Ground Personnel"/> 
      <perskill skill="sk01"/> 
      <trade>welder</trade> 
      <esttime>.5 hr</esttime> 

      <asrequir/> 
      <perscat category="2nd Required Category"/> 
      <esttime>4 days</esttime> 

      <person man="D" id="pers_d"/> 
      <perscat category="Rides in Chase Vehicle"/> 
      <perskill skill="sk02"/> 

      <person man="E"/> 
      <perscat category="Jack of all Trades"/> 
      <trade>engine mechanic</trade> 
    </reqpers> 
    </code> 
    </pre> 

甲行需要为每个人或asrequir元件,然后将细胞用于填充组这些元件之间的兄弟姐妹的行被创建。 我已经看过很多例子,包括:How to select siblings

这一个:How to select group of siblings

以及许多其他的。这些都不涉及我的具体问题集,这主要是在XPath查询中有两个以下的兄弟姐妹需要处理。 这里的表应该是什么样子的例子:

<pre class="prettyprint"><code class="language-xml"> 
    <table> 
     <table-header> 
      <table-row> 
       <table-cell> Person </table-cell> 
       <table-cell> Category/Trade </table-cell> 
       <table-cell> Skill level </table-cell> 
       <table-cell> Trade code </table-cell> 
       <table-cell> Estimated time </table-cell> 
      </table-row> 
     </table-header> 
     <table-body> 
      <table-row> 
       <table-cell>Four</table-cell> 
       <table-cell/> 
       <table-cell/> 
       <table-cell/> 
       <table-cell/> 
      </table-row> 
      <table-row> 
       <table-cell>A</table-cell> 
       <table-cell>Recovery Supervisor</table-cell> 
       <table-cell/> 
       <table-cell/> 
       <table-cell/> 
      </table-row> 
      <table-row> 
       <table-cell>B</table-cell> 
       <table-cell>Ground Personnel</table-cell> 
       <table-cell/> 
       <table-cell/> 
       <table-cell/> 
      </table-row> 
      <table-row> 
       <table-cell>As required</table-cell> 
       <table-cell/> 
       <table-cell/> 
       <table-cell>Bill Collector</table-cell> 
       <table-cell/> 
      </table-row> 
      <table-row> 
       <table-cell>C</table-cell> 
       <table-cell>Ground Personnel</table-cell> 
       <table-cell>skill gets converted to string value</table-cell> 
       <table-cell>welder</table-cell> 
       <table-cell>.5 hr</table-cell> 
      </table-row> 
      <table-row> 
       <table-cell>As required</table-cell> 
       <table-cell>2nd Required Category</table-cell> 
       <table-cell/> 
       <table-cell/> 
       <table-cell>4 days</table-cell> 
      </table-row> 
      <table-row> 
       <table-cell>D</table-cell> 
       <table-cell>Rides in Chase Vehicle</table-cell> 
       <table-cell>skill level</table-cell> 
       <table-cell/> 
       <table-cell/> 
      </table-row> 
      <table-row> 
       <table-cell>E</table-cell> 
       <table-cell>Jack of all Trades</table-cell> 
       <table-cell/> 
       <table-cell>engine mechanic</table-cell> 
       <table-cell/> 
      </table-row> 
     </table-body> 
    </table> 
</code> 
     </pre> 

同样的完整性,这是对XML架构片断我处理:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" 
<xs:element name="reqpers" type="reqpersType"/> 
<xs:complexType name="reqpersType"> 
    <xs:sequence> 
     <xs:element minOccurs="0" ref="applic"/> 
     <xs:sequence maxOccurs="unbounded"> 
      <xs:choice> 
       <xs:element ref="asrequir"/> 
       <xs:element ref="person"/> 
      </xs:choice> 
      <xs:sequence minOccurs="0"> 
       <xs:element ref="perscat"/> 
       <xs:element minOccurs="0" ref="perskill"/> 
       <xs:element minOccurs="0" ref="trade"/> 
       <xs:element minOccurs="0" ref="esttime"/> 
      </xs:sequence> 
     </xs:sequence> 
    </xs:sequence> 
    <xs:attribute ref="refapplic"/> 
    <xs:attributeGroup ref="bodyatt"/> 
    <xs:attributeGroup ref="cntlcontent"/> 
</xs:complexType> 

这里是一个最接近的xsl代码的例子,但它只适用于有人的兄弟姐妹,一旦asrequir被添加的东西分崩离析。我基本上重复每个单元格的代码,用我期望的元素替换perscat。

<xsl:for-each select="person | asrequir"> 
      <fo:table-row> 
       <fo:table-cell text-align="left" padding-before="1mm" padding-after="1mm" padding-left="1mm" padding-right="1mm"> 
        <fo:block font-size="10pt"> 
         <xsl:value-of select="self::person/@man"/> 
        </fo:block> 
       </fo:table-cell> 
    <fo:table-cell text-align="left" padding-before="1mm" padding-after="1mm" padding-left="1mm" padding-right="1mm"> 
     <xsl:variable name="perscatSib" select="following-sibling::perscat"/> 
     <xsl:variable name="perscatPrec" select="following-sibling::person[1]/preceding-sibling::perscat"/> 
     <fo:block font-size="10pt"> 
      <xsl:choose> 
       <xsl:when test="$perscatSib[count(. | $perscatPrec) = count($perscatPrec)]"> 
        <xsl:value-of select="$perscatSib[count(. | $perscatPrec) = count($perscatPrec)]/@category"/> 
       </xsl:when> 
       <xsl:otherwise> 
        <xsl:if test="preceding-sibling::person[1] and not(following-sibling::person[1])"> 
         <xsl:value-of select="following-sibling::perscat[1]/@category"/> 
        </xsl:if> 
       </xsl:otherwise> 
      </xsl:choose> 
     </fo:block> 
    </fo:table-cell> 
<continues with the rest of the cells../> 

这是我制作的表格:

<pre class="prettyprint"><code class="language-xml"> 
<table> 
    <table-header> 
     <table-row> 
      <table-cell> Person </table-cell> 
      <table-cell> Category/Trade </table-cell> 
      <table-cell> Skill level </table-cell> 
      <table-cell> Trade code </table-cell> 
      <table-cell> Estimated time </table-cell> 
     </table-row> 
    </table-header> 
    <table-body> 
     <table-row> 
      <table-cell>Four</table-cell> 
      <table-cell/> 
      <table-cell/> 
      <table-cell/> 
      <table-cell/> 
     </table-row> 
     <table-row> 
      <table-cell>A</table-cell> 
      <table-cell>Recovery Supervisor</table-cell> 
      <table-cell/> 
      <table-cell/> 
      <table-cell/> 
     </table-row> 
     <table-row> 
      <table-cell>B</table-cell> 
      <table-cell>Ground Personnel</table-cell> 
      <table-cell/> 
      **<table-cell>BillCollector</table-cell>** 
      <table-cell/> 
     </table-row> 
     <table-row> 
      <table-cell>As required</table-cell> 
      <table-cell/> 
      <table-cell/> 
      <table-cell>Bill Collector</table-cell> 
      <table-cell/> 
     </table-row> 
     <table-row> 
      <table-cell>C</table-cell> 
      <table-cell>Ground Personnel</table-cell> 
      <table-cell>skill gets converted to string value</table-cell> 
      <table-cell>welder</table-cell> 
      <table-cell>.5 hr</table-cell> 
     </table-row> 
     <table-row> 
      <table-cell>As required</table-cell> 
      <table-cell>2nd Required Category</table-cell> 
      <table-cell/> 
      <table-cell/> 
      <table-cell>4 days</table-cell> 
     </table-row> 
     <table-row> 
      <table-cell>D</table-cell> 
      <table-cell>Rides in Chase Vehicle</table-cell> 
      <table-cell>skill level</table-cell> 
      <table-cell/> 
      <table-cell/> 
     </table-row> 
     <table-row> 
      <table-cell>E</table-cell> 
      <table-cell>Jack of all Trades</table-cell> 
      <table-cell/> 
      <table-cell>engine mechanic</table-cell> 
      <table-cell/> 
     </table-row> 
    </table-body> 
</table> 
</code> 
     </pre> 

与**的表格单元格周围不应该有它的数据。它增加了从以下asrequir这是不是值我想要什么..

我已经尝试添加以下 - 兄弟::人['1'] | asrequir ['1']但asrequir总是如此,所以我得到额外的兄弟姐妹在我不想要的地方。任何有关如何解决这个问题的见解或建议将非常感谢。我怀疑我需要使用某种类别的密钥或密钥集合,但不知道如何实现这些。虽然不是XSLT和XPath的新手,但我不是专家。

+1

您可以使用XSLT 2.0和-各组组启动,用? –

+0

现在我暂时停留在XSLT 1.0中。 –

回答

2

一个密钥可以帮助将来自reqpers的非person or asrequir的所有元素分组到前兄弟姐妹或asrequir。

<xsl:for-each select="*[self::person or self::asrequir]"> 

小组成员则:

<xsl:variable name="this" select="." /> 
    <xsl:variable name="group" select=". | key('kperson',generate-id($this))" /> 

从组获取的值:

<xsl:value-of select="$group[self::perscat]/@category"/> 

你可以试试这个

<xsl:key name="kperson" match="reqpers/*[not(self::person or self::asrequir)]" 
     use="generate-id(preceding-sibling::*[self::person or self::asrequir][1]) 

与本集团统计:

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

    <xsl:key name="kperson" match="reqpers/*[not(self::person or self::asrequir)]" 
      use="generate-id(preceding-sibling::*[self::person or self::asrequir][1])"/> 
    <xsl:template match="reqpers"> 
    <table> 
    <table-header> 
     <table-row> 
      <table-cell> Person </table-cell> 
      <table-cell> Category/Trade </table-cell> 
      <table-cell> Skill level </table-cell> 
      <table-cell> Trade code </table-cell> 
      <table-cell> Estimated time </table-cell> 
     </table-row> 
    </table-header> 
    <xsl:for-each select="*[self::person or self::asrequir]"> 

     <xsl:variable name="this" select="." /> 
     <xsl:variable name="group" select=". | key('kperson',generate-id($this))" /> 
     <table-row> 
      <table-cell> 
       <xsl:value-of select="$group[self::person]/@man"/> 
       <xsl:if test="$group[self::asrequir]" >As required</xsl:if> 
      </table-cell> 
      <table-cell><xsl:value-of select="$group[self::perscat]/@category"/></table-cell> 
      <table-cell><xsl:value-of select="$group[self::perskill]/@skill"/></table-cell> 
      <table-cell><xsl:value-of select="$group[self::trade]"/></table-cell> 
      <table-cell><xsl:value-of select="$group[self::esttime]"/></table-cell> 
     </table-row> 
    </xsl:for-each> 
    </table> 
    </xsl:template> 

</xsl:stylesheet> 

有了以下的输出:

<table> 
    <table-header> 
    <table-row> 
     <table-cell> Person </table-cell> 
     <table-cell> Category/Trade </table-cell> 
     <table-cell> Skill level </table-cell> 
     <table-cell> Trade code </table-cell> 
     <table-cell> Estimated time </table-cell> 
    </table-row> 
    </table-header> 
    <table-row> 
    <table-cell>Four</table-cell> 
    <table-cell/> 
    <table-cell/> 
    <table-cell/> 
    <table-cell/> 
    </table-row> 
    <table-row> 
    <table-cell>A</table-cell> 
    <table-cell>Recovery Supervisor</table-cell> 
    <table-cell/> 
    <table-cell/> 
    <table-cell/> 
    </table-row> 
    <table-row> 
    <table-cell>B</table-cell> 
    <table-cell>Ground Personnel</table-cell> 
    <table-cell/> 
    <table-cell/> 
    <table-cell/> 
    </table-row> 
    <table-row> 
    <table-cell>As required</table-cell> 
    <table-cell>As Required Category</table-cell> 
    <table-cell/> 
    <table-cell>Bill Collector</table-cell> 
    <table-cell/> 
    </table-row> 
    <table-row> 
    <table-cell>C</table-cell> 
    <table-cell>Ground Personnel</table-cell> 
    <table-cell>sk01</table-cell> 
    <table-cell>welder</table-cell> 
    <table-cell>.5 hr</table-cell> 
    </table-row> 
    <table-row> 
    <table-cell>As required</table-cell> 
    <table-cell>2nd Required Category</table-cell> 
    <table-cell/> 
    <table-cell/> 
    <table-cell>4 days</table-cell> 
    </table-row> 
    <table-row> 
    <table-cell>D</table-cell> 
    <table-cell>Rides in Chase Vehicle</table-cell> 
    <table-cell>sk02</table-cell> 
    <table-cell/> 
    <table-cell/> 
    </table-row> 
    <table-row> 
    <table-cell>E</table-cell> 
    <table-cell>Jack of all Trades</table-cell> 
    <table-cell/> 
    <table-cell>engine mechanic</table-cell> 
    <table-cell/> 
    </table-row> 
</table>