Xml XSL头和细节分组

Xml XSL头和细节分组,xml,xslt-1.0,Xml,Xslt 1.0,我正试图从一个包含多个标题行、每个标题后跟多个详细信息行的文件中创建一组xml 以下是原始XML的一个示例: 编辑:标题图纸后面的详图图纸数量将有所不同。因此,表[4]/FIELD1并不总是具有Header的值。此外,该文件将始终具有一个或多个标题页。床单是一排排的 编辑:XSLT-1.0 标题 价值1 价值2 细节 价值3 价值4 细节 价值5 价值6 标题 价值7 价值8 细节 价值9 价值10 细节 价值11 价值12 细节 价值13 价值14 以下是输出应该类似的内容: 编辑:发票的

我正试图从一个包含多个标题行、每个标题后跟多个详细信息行的文件中创建一组xml

以下是原始XML的一个示例:

编辑:标题图纸后面的详图图纸数量将有所不同。因此,表[4]/FIELD1并不总是具有Header的值。此外,该文件将始终具有一个或多个标题页。床单是一排排的

编辑:XSLT-1.0


标题
价值1
价值2
细节
价值3
价值4
细节
价值5
价值6
标题
价值7
价值8
细节
价值9
价值10
细节
价值11
价值12
细节
价值13
价值14
以下是输出应该类似的内容:

编辑:发票的数量将由标题页(行)的数量决定。行项目行数将与页眉后面的详图图纸数相同


编辑:回答如下:

试试这个:

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

    <xsl:template match="Root">
        <xsl:copy>
            <Invoice AttribOne="{Sheet[1]/FIELD2}" AttribTwo="{Sheet[1]/FIELD3}">
                <xsl:apply-templates select="Sheet[2] | Sheet[3]"/>
            </Invoice>
            <Invoice AttribOne="{Sheet[4]/FIELD2}" AttribTwo="{Sheet[4]/FIELD3}">
                <xsl:apply-templates select="Sheet[5] | Sheet[6] | Sheet[7]"/>
            </Invoice>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="Sheet">
        <LineItem LIAttribOne="{FIELD2}" LIAttribTwo="{FIELD3}"/>
    </xsl:template>

</xsl:stylesheet>

我已经解决了这个问题,并在下面的代码中添加了注释来描述它

以下是解决方案:

<xsl:template match="/Root">
    <Root>
         <xsl:apply-templates select="Sheet[FIELD1 = 'Header']" />
    </Root>
</xsl:template>

<xsl:template match="Sheet[FIELD1 = 'Detail']" >
    <LineItem>
      <xsl:attribute name="LIAttribOne" >
        <xsl:value-of select="FIELD2"/>
      </xsl:attribute>
      <xsl:attribute name="LIAttribTwo" >
        <xsl:value-of select="FIELD3"/>
      </xsl:attribute>
    </LineItem>
</xsl:template>

<xsl:template  match="Sheet[FIELD1 = 'Header']">
    <Invoice>
      <xsl:attribute name="AttribOne" >
        <xsl:value-of select="FIELD2"/>
      </xsl:attribute>
      <xsl:attribute name="AttribTwo" >
        <xsl:value-of select="FIELD3"/>
      </xsl:attribute>
  <!-- Get the count of all details the previous headers contained -->
  <xsl:variable name="prevCnt" select="count(preceding-sibling::*[FIELD1 = 'Detail'])"/>
  <!-- Get the count of all details in the previous headers and this header contain -->
  <xsl:variable name="newCnt" select="count(following-sibling::*[FIELD1 = 'Header'][1]/preceding-sibling::*[FIELD1 = 'Detail'])"/>
  <!-- This will return a 1 if there is a following header, else 0 -->
  <xsl:variable name="pos" select="count(following-sibling::*[FIELD1 = 'Header'][1])" />
  <!-- select every detail whose position is less than $newCnt - $preCnt or all if there is no following header -->
  <xsl:apply-templates select="following-sibling::*[FIELD1 = 'Detail'][position() &lt; ($newCnt - $prevCnt + 1) or $pos = 0]"   />
</Invoice>


感谢您的回复。这是行不通的,因为哪张工作表具有标题值(尽管[1]肯定会),哪张工作表具有详细信息值将因文件而异。这将生成您在上面发布的内容。您是否有其他未提及的要求?您可以使用
/Root/Sheet[1]/FIELD1
/Root/Sheet[4]/FIELD1
获取标题值,以及其他
/Root/Sheet[n]/FIELD1
中的详细值。对于我在原始帖子中没有提供足够的信息,我深表歉意。我用一些编辑注释对它进行了更新。如果有任何方法可以区分标题和细节,那么它可以被递归处理。单词“Header”和“Detail”是否重要,或者它们是否包含其他值?确定。如何识别标题字段?还是细节字段?“标题”和“细节”这两个词是否重要?工作表/字段1的值始终为“标题”或“细节”。两张纸之间没有其他区别。
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes"/>

    <xsl:template match="Root">
        <xsl:copy>
            <Invoice AttribOne="{Sheet[1]/FIELD2}" AttribTwo="{Sheet[1]/FIELD3}">
                <xsl:apply-templates select="Sheet[2] | Sheet[3]"/>
            </Invoice>
            <Invoice AttribOne="{Sheet[4]/FIELD2}" AttribTwo="{Sheet[4]/FIELD3}">
                <xsl:apply-templates select="Sheet[5] | Sheet[6] | Sheet[7]"/>
            </Invoice>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="Sheet">
        <LineItem LIAttribOne="{FIELD2}" LIAttribTwo="{FIELD3}"/>
    </xsl:template>

</xsl:stylesheet>
<xsl:template match="/Root">
    <Root>
         <xsl:apply-templates select="Sheet[FIELD1 = 'Header']" />
    </Root>
</xsl:template>

<xsl:template match="Sheet[FIELD1 = 'Detail']" >
    <LineItem>
      <xsl:attribute name="LIAttribOne" >
        <xsl:value-of select="FIELD2"/>
      </xsl:attribute>
      <xsl:attribute name="LIAttribTwo" >
        <xsl:value-of select="FIELD3"/>
      </xsl:attribute>
    </LineItem>
</xsl:template>

<xsl:template  match="Sheet[FIELD1 = 'Header']">
    <Invoice>
      <xsl:attribute name="AttribOne" >
        <xsl:value-of select="FIELD2"/>
      </xsl:attribute>
      <xsl:attribute name="AttribTwo" >
        <xsl:value-of select="FIELD3"/>
      </xsl:attribute>
  <!-- Get the count of all details the previous headers contained -->
  <xsl:variable name="prevCnt" select="count(preceding-sibling::*[FIELD1 = 'Detail'])"/>
  <!-- Get the count of all details in the previous headers and this header contain -->
  <xsl:variable name="newCnt" select="count(following-sibling::*[FIELD1 = 'Header'][1]/preceding-sibling::*[FIELD1 = 'Detail'])"/>
  <!-- This will return a 1 if there is a following header, else 0 -->
  <xsl:variable name="pos" select="count(following-sibling::*[FIELD1 = 'Header'][1])" />
  <!-- select every detail whose position is less than $newCnt - $preCnt or all if there is no following header -->
  <xsl:apply-templates select="following-sibling::*[FIELD1 = 'Detail'][position() &lt; ($newCnt - $prevCnt + 1) or $pos = 0]"   />
</Invoice>