分组元素未按要求的结构出现
Grouping elements not appearing as per required structure
我尝试根据 @style 对元素进行分组,所有情况看起来都很好,只是这里的问题是第一个 p[@style="TRH7" 在 TRH4 之前没有关闭。
我参考了 here 但运气不好。
输入XML:
<?xml version="1.0" encoding="UTF-8"?>
<text width="12240" height="15840" orient="">
<p type="itemlist" id-rel="1" level="1" style="TRH2">
<r>Test scenario 1 (TRH2) /chapter/title</r>
</p>
<p type="itemlist" id-rel="1" level="6" style="TRH7">
<r>Test Scenario 2 (TRH7) /chapter/section/title</r>
</p>
<p style="TRNormal">
<r>Test Scenario 3 (TRNormal) /chapter/section/paragraph </r>
</p>
<table>a</table>
<p type="itemlist" id-rel="1" level="3" style="TRH4">
<r>Test Scenario 4 (TRH4) /chapter/division/title</r>
</p>
<p type="itemlist" id-rel="1" level="6" style="TRH7">
<r>Test Scenario 5 (TRH7) /chapter/division/section/title</r>
</p>
<p style="TRNormal">
<r>Test Scenario 6 (TRNormal) /chapter/division/section/paragraph </r>
</p>
<p type="itemlist" id-rel="1" level="4" style="TRH5">
<r>Test Scenario 7 (TRH5) /chapter/division/subdivision/title</r>
</p>
<p type="itemlist" id-rel="1" level="5" style="TRH6">
<r>Test Scenario 8 (TRH6) /chapter/division/subdivision/arabicSubdivision/title</r>
</p>
<p type="itemlist" id-rel="1" level="6" style="TRH7">
<r>Test Scenario 9 (TRH7) /chapter/division/subdivision/arabicSubdivision/section/title</r>
</p>
<p style="TRNormal">
<r>Test Scenario 10 (TRNormal)
/chapter/division/subdivision/arabicSubdivision/section/paragraph </r>
</p>
<p style="TRNormal">
<r>Test 1 </r>
</p>
<p style="TRNormal">
<r>Test 2 </r>
</p>
</text>
当前 XSL:
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:mf="http://example.com/mf"
exclude-result-prefixes="xs mf"
version="2.0">
<xsl:strip-space elements="*"/>
<xsl:output indent="yes" method="xml"/>
<xsl:function name="mf:group" as="node()*">
<xsl:param name="elements" as="element()*"/>
<xsl:param name="level" as="xs:integer"/>
<xsl:for-each-group select="$elements" group-starting-with="p[@style eq concat('TRH', $level)]">
<xsl:choose>
<xsl:when test="self::p[@style eq 'TRH2']">
<chapter> <!--level="{$level}"-->
<title><xsl:apply-templates select="node()"/></title>
<xsl:sequence select="mf:group(current-group() except ., $level + 1)"/>
</chapter>
</xsl:when>
<xsl:when test="self::p[@style eq 'TRH4']">
<division> <!--level="{$level}"-->
<title><xsl:apply-templates select="node()"/></title>
<xsl:sequence select="mf:group(current-group() except ., $level + 1)"/>
</division>
</xsl:when>
<xsl:when test="self::p[@style eq 'TRH5']">
<subdivision> <!--level="{$level}"-->
<title><xsl:apply-templates select="node()"/></title>
<xsl:sequence select="mf:group(current-group() except ., $level + 1)"/>
</subdivision>
</xsl:when>
<xsl:when test="self::p[@style eq 'TRH6']">
<arabicSubdivision> <!--level="{$level}"-->
<title><xsl:apply-templates select="node()"/></title>
<xsl:sequence select="mf:group(current-group() except ., $level + 1)"/>
</arabicSubdivision>
</xsl:when>
<xsl:when test="self::p[@style eq 'TRH7']">
<section> <!--level="{$level}"-->
<title><xsl:apply-templates select="node()"/></title>
<xsl:sequence select="mf:group(current-group() except ., $level + 1)"/>
</section>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="current-group()"/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:function>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@*, node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="p">
<paragraph><xsl:apply-templates/></paragraph>
</xsl:template>
<xsl:template match="text">
<xsl:sequence select="mf:group(*, 2)"/>
</xsl:template>
<xsl:template match="r">
<xsl:apply-templates/>
</xsl:template>
</xsl:stylesheet>
当前输出:
<?xml version="1.0" encoding="UTF-8"?>
<chapter>
<title>Test scenario 1 (TRH2) /chapter/title</title>
<section>
<title>Test Scenario 2 (TRH7) /chapter/section/title</title>
<paragraph>Test Scenario 3 (TRNormal) /chapter/section/paragraph </paragraph>
<table>a</table>
<division>
<title>Test Scenario 4 (TRH4) /chapter/division/title</title>
<section>
<title>Test Scenario 5 (TRH7) /chapter/division/section/title</title>
<paragraph>Test Scenario 6 (TRNormal) /chapter/division/section/paragraph </paragraph>
</section>
<subdivision>
<title>Test Scenario 7 (TRH5) /chapter/division/subdivision/title</title>
<arabicSubdivision>
<title>Test Scenario 8 (TRH6) /chapter/division/subdivision/arabicSubdivision/title</title>
<section>
<title>Test Scenario 9 (TRH7) /chapter/division/subdivision/arabicSubdivision/section/title</title>
<paragraph>Test Scenario 10 (TRNormal)
/chapter/division/subdivision/arabicSubdivision/section/paragraph </paragraph>
<paragraph>Test 1 </paragraph>
<paragraph>Test 2 </paragraph>
</section>
</arabicSubdivision>
</subdivision>
</division>
</section>
</chapter>
期望输出:
<?xml version="1.0" encoding="UTF-8"?>
<chapter>
<title>Test scenario 1 (TRH2) /chapter/title</title>
<section>
<title>Test Scenario 2 (TRH7) /chapter/section/title</title>
<paragraph>Test Scenario 3 (TRNormal) /chapter/section/paragraph </paragraph>
<table>a</table>
</section>
<division>
<title>Test Scenario 4 (TRH4) /chapter/division/title</title>
<section>
<title>Test Scenario 5 (TRH7) /chapter/division/section/title</title>
<paragraph>Test Scenario 6 (TRNormal) /chapter/division/section/paragraph </paragraph>
</section>
<subdivision>
<title>Test Scenario 7 (TRH5) /chapter/division/subdivision/title</title>
<arabicSubdivision>
<title>Test Scenario 8 (TRH6) /chapter/division/subdivision/arabicSubdivision/title</title>
<section>
<title>Test Scenario 9 (TRH7) /chapter/division/subdivision/arabicSubdivision/section/title</title>
<paragraph>Test Scenario 10 (TRNormal)
/chapter/division/subdivision/arabicSubdivision/section/paragraph </paragraph>
<paragraph>Test 1 </paragraph>
<paragraph>Test 2 </paragraph>
</section>
</arabicSubdivision>
</subdivision>
</division>
</chapter>
最近出现了一个类似的问题 Not able to do XSLT transformation with grouping, to which I posted the answer ,要使其与您的输入兼容,其中 p
元素与 table
元素混合,您需要将函数参数键入为element()*
而不是 element(p)*
:
<?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:map="http://www.w3.org/2005/xpath-functions/map"
exclude-result-prefixes="#all"
xmlns:mf="http://example.com/mf">
<xsl:param name="xml-levels-param">
<levels>
<level key="TRH2">
<container>chapter</container>
<content>title</content>
</level>
<level key="TRH4">
<container>division</container>
<content>title</content>
</level>
<level key="TRH5">
<container>subdivision</container>
<content>title</content>
</level>
<level key="TRH6">
<container>arabicSubdivision</container>
<content>title</content>
</level>
<level key="TRH7">
<container>section</container>
<content>title</content>
</level>
</levels>
</xsl:param>
<xsl:variable name="xml-levels" select="$xml-levels-param/levels/level"/>
<xsl:function name="mf:group-xml" as="node()*">
<xsl:param name="elements" as="element()*"/>
<xsl:param name="level" as="xs:integer"/>
<xsl:for-each-group select="$elements" group-starting-with="p[@style = $xml-levels[$level]/@key]">
<xsl:choose>
<xsl:when test="self::p[@style = $xml-levels[$level]/@key]">
<xsl:element name="{$xml-levels[$level]/container}">
<xsl:element name="{$xml-levels[$level]/content}">
<xsl:value-of select="r"/>
</xsl:element>
<xsl:choose>
<xsl:when test="exists($xml-levels[$level + 1])">
<xsl:sequence select="mf:group-xml(current-group()[position() gt 1], $level + 1)"/>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="current-group()[position() gt 1]"/>
</xsl:otherwise>
</xsl:choose>
</xsl:element>
</xsl:when>
<xsl:otherwise>
<xsl:choose>
<xsl:when test="exists($xml-levels[$level + 1])">
<xsl:sequence select="mf:group-xml(current-group(), $level + 1)"/>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="current-group()"/>
</xsl:otherwise>
</xsl:choose>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:function>
<xsl:template match="text">
<xsl:sequence select="mf:group-xml(*, 1)"/>
</xsl:template>
<xsl:template match="p[@style = 'TRNormal']">
<paragraphp>
<xsl:apply-templates select="r/node()"/>
</paragraphp>
</xsl:template>
<xsl:template match="p[not(node())]"/>
<xsl:output method="xml" indent="yes"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
我尝试根据 @style 对元素进行分组,所有情况看起来都很好,只是这里的问题是第一个 p[@style="TRH7" 在 TRH4 之前没有关闭。
我参考了 here 但运气不好。
输入XML:
<?xml version="1.0" encoding="UTF-8"?>
<text width="12240" height="15840" orient="">
<p type="itemlist" id-rel="1" level="1" style="TRH2">
<r>Test scenario 1 (TRH2) /chapter/title</r>
</p>
<p type="itemlist" id-rel="1" level="6" style="TRH7">
<r>Test Scenario 2 (TRH7) /chapter/section/title</r>
</p>
<p style="TRNormal">
<r>Test Scenario 3 (TRNormal) /chapter/section/paragraph </r>
</p>
<table>a</table>
<p type="itemlist" id-rel="1" level="3" style="TRH4">
<r>Test Scenario 4 (TRH4) /chapter/division/title</r>
</p>
<p type="itemlist" id-rel="1" level="6" style="TRH7">
<r>Test Scenario 5 (TRH7) /chapter/division/section/title</r>
</p>
<p style="TRNormal">
<r>Test Scenario 6 (TRNormal) /chapter/division/section/paragraph </r>
</p>
<p type="itemlist" id-rel="1" level="4" style="TRH5">
<r>Test Scenario 7 (TRH5) /chapter/division/subdivision/title</r>
</p>
<p type="itemlist" id-rel="1" level="5" style="TRH6">
<r>Test Scenario 8 (TRH6) /chapter/division/subdivision/arabicSubdivision/title</r>
</p>
<p type="itemlist" id-rel="1" level="6" style="TRH7">
<r>Test Scenario 9 (TRH7) /chapter/division/subdivision/arabicSubdivision/section/title</r>
</p>
<p style="TRNormal">
<r>Test Scenario 10 (TRNormal)
/chapter/division/subdivision/arabicSubdivision/section/paragraph </r>
</p>
<p style="TRNormal">
<r>Test 1 </r>
</p>
<p style="TRNormal">
<r>Test 2 </r>
</p>
</text>
当前 XSL:
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:mf="http://example.com/mf"
exclude-result-prefixes="xs mf"
version="2.0">
<xsl:strip-space elements="*"/>
<xsl:output indent="yes" method="xml"/>
<xsl:function name="mf:group" as="node()*">
<xsl:param name="elements" as="element()*"/>
<xsl:param name="level" as="xs:integer"/>
<xsl:for-each-group select="$elements" group-starting-with="p[@style eq concat('TRH', $level)]">
<xsl:choose>
<xsl:when test="self::p[@style eq 'TRH2']">
<chapter> <!--level="{$level}"-->
<title><xsl:apply-templates select="node()"/></title>
<xsl:sequence select="mf:group(current-group() except ., $level + 1)"/>
</chapter>
</xsl:when>
<xsl:when test="self::p[@style eq 'TRH4']">
<division> <!--level="{$level}"-->
<title><xsl:apply-templates select="node()"/></title>
<xsl:sequence select="mf:group(current-group() except ., $level + 1)"/>
</division>
</xsl:when>
<xsl:when test="self::p[@style eq 'TRH5']">
<subdivision> <!--level="{$level}"-->
<title><xsl:apply-templates select="node()"/></title>
<xsl:sequence select="mf:group(current-group() except ., $level + 1)"/>
</subdivision>
</xsl:when>
<xsl:when test="self::p[@style eq 'TRH6']">
<arabicSubdivision> <!--level="{$level}"-->
<title><xsl:apply-templates select="node()"/></title>
<xsl:sequence select="mf:group(current-group() except ., $level + 1)"/>
</arabicSubdivision>
</xsl:when>
<xsl:when test="self::p[@style eq 'TRH7']">
<section> <!--level="{$level}"-->
<title><xsl:apply-templates select="node()"/></title>
<xsl:sequence select="mf:group(current-group() except ., $level + 1)"/>
</section>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="current-group()"/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:function>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@*, node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="p">
<paragraph><xsl:apply-templates/></paragraph>
</xsl:template>
<xsl:template match="text">
<xsl:sequence select="mf:group(*, 2)"/>
</xsl:template>
<xsl:template match="r">
<xsl:apply-templates/>
</xsl:template>
</xsl:stylesheet>
当前输出:
<?xml version="1.0" encoding="UTF-8"?>
<chapter>
<title>Test scenario 1 (TRH2) /chapter/title</title>
<section>
<title>Test Scenario 2 (TRH7) /chapter/section/title</title>
<paragraph>Test Scenario 3 (TRNormal) /chapter/section/paragraph </paragraph>
<table>a</table>
<division>
<title>Test Scenario 4 (TRH4) /chapter/division/title</title>
<section>
<title>Test Scenario 5 (TRH7) /chapter/division/section/title</title>
<paragraph>Test Scenario 6 (TRNormal) /chapter/division/section/paragraph </paragraph>
</section>
<subdivision>
<title>Test Scenario 7 (TRH5) /chapter/division/subdivision/title</title>
<arabicSubdivision>
<title>Test Scenario 8 (TRH6) /chapter/division/subdivision/arabicSubdivision/title</title>
<section>
<title>Test Scenario 9 (TRH7) /chapter/division/subdivision/arabicSubdivision/section/title</title>
<paragraph>Test Scenario 10 (TRNormal)
/chapter/division/subdivision/arabicSubdivision/section/paragraph </paragraph>
<paragraph>Test 1 </paragraph>
<paragraph>Test 2 </paragraph>
</section>
</arabicSubdivision>
</subdivision>
</division>
</section>
</chapter>
期望输出:
<?xml version="1.0" encoding="UTF-8"?>
<chapter>
<title>Test scenario 1 (TRH2) /chapter/title</title>
<section>
<title>Test Scenario 2 (TRH7) /chapter/section/title</title>
<paragraph>Test Scenario 3 (TRNormal) /chapter/section/paragraph </paragraph>
<table>a</table>
</section>
<division>
<title>Test Scenario 4 (TRH4) /chapter/division/title</title>
<section>
<title>Test Scenario 5 (TRH7) /chapter/division/section/title</title>
<paragraph>Test Scenario 6 (TRNormal) /chapter/division/section/paragraph </paragraph>
</section>
<subdivision>
<title>Test Scenario 7 (TRH5) /chapter/division/subdivision/title</title>
<arabicSubdivision>
<title>Test Scenario 8 (TRH6) /chapter/division/subdivision/arabicSubdivision/title</title>
<section>
<title>Test Scenario 9 (TRH7) /chapter/division/subdivision/arabicSubdivision/section/title</title>
<paragraph>Test Scenario 10 (TRNormal)
/chapter/division/subdivision/arabicSubdivision/section/paragraph </paragraph>
<paragraph>Test 1 </paragraph>
<paragraph>Test 2 </paragraph>
</section>
</arabicSubdivision>
</subdivision>
</division>
</chapter>
最近出现了一个类似的问题 Not able to do XSLT transformation with grouping, to which I posted the answer ,要使其与您的输入兼容,其中 p
元素与 table
元素混合,您需要将函数参数键入为element()*
而不是 element(p)*
:
<?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:map="http://www.w3.org/2005/xpath-functions/map"
exclude-result-prefixes="#all"
xmlns:mf="http://example.com/mf">
<xsl:param name="xml-levels-param">
<levels>
<level key="TRH2">
<container>chapter</container>
<content>title</content>
</level>
<level key="TRH4">
<container>division</container>
<content>title</content>
</level>
<level key="TRH5">
<container>subdivision</container>
<content>title</content>
</level>
<level key="TRH6">
<container>arabicSubdivision</container>
<content>title</content>
</level>
<level key="TRH7">
<container>section</container>
<content>title</content>
</level>
</levels>
</xsl:param>
<xsl:variable name="xml-levels" select="$xml-levels-param/levels/level"/>
<xsl:function name="mf:group-xml" as="node()*">
<xsl:param name="elements" as="element()*"/>
<xsl:param name="level" as="xs:integer"/>
<xsl:for-each-group select="$elements" group-starting-with="p[@style = $xml-levels[$level]/@key]">
<xsl:choose>
<xsl:when test="self::p[@style = $xml-levels[$level]/@key]">
<xsl:element name="{$xml-levels[$level]/container}">
<xsl:element name="{$xml-levels[$level]/content}">
<xsl:value-of select="r"/>
</xsl:element>
<xsl:choose>
<xsl:when test="exists($xml-levels[$level + 1])">
<xsl:sequence select="mf:group-xml(current-group()[position() gt 1], $level + 1)"/>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="current-group()[position() gt 1]"/>
</xsl:otherwise>
</xsl:choose>
</xsl:element>
</xsl:when>
<xsl:otherwise>
<xsl:choose>
<xsl:when test="exists($xml-levels[$level + 1])">
<xsl:sequence select="mf:group-xml(current-group(), $level + 1)"/>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="current-group()"/>
</xsl:otherwise>
</xsl:choose>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:function>
<xsl:template match="text">
<xsl:sequence select="mf:group-xml(*, 1)"/>
</xsl:template>
<xsl:template match="p[@style = 'TRNormal']">
<paragraphp>
<xsl:apply-templates select="r/node()"/>
</paragraphp>
</xsl:template>
<xsl:template match="p[not(node())]"/>
<xsl:output method="xml" indent="yes"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>