xsl - 根据 2 个节点之间的属性对节点进行分组

发布于 2024-10-31 09:20:19 字数 1618 浏览 0 评论 0原文

在 XSL 1.0 中,我进行了搜索并发现了有关分组的类似项目,但我认为这略有不同。 抱歉,如果这已经被涵盖,我无法找到答案

输入

<?xml version="1.0"?>
<xmldoc>
<section paragraphMarker="true">Part 1. </section>
<section paragraphMarker="false">Part 2. </section>
<section paragraphMarker="false">Part 3. </section>
<section paragraphMarker="true">Part 4. </section>
<section paragraphMarker="true">Part 5. </section>
<section paragraphMarker="false">Part 6. </section>
</xmldoc>

所需输出

<p>Part 1. Part 2. Part 3.</p>
<p>Part 4. </p>
<p>Part 5. Part 6. </p>

我已尝试以下操作:-

<xsl:key name="sectionsWithParagraphMarker" 
    match="section[@paragraphMarker='true']" use="."/>

<xsl:template match="/">
<xsl:for-each select=
    "/xmldoc/section[generate-id()
         = 
    generate-id(key('sectionsWithParagraphMarker',.)[1])]">
   <p>
<xsl:apply-templates select="."/>
<xsl:apply-templates select="./following-sibling::node()
         [count(. | /xmldoc/section[@paragraphMarker='true'][1]/
             preceding-sibling::node())
         =
         count(/xmldoc/section[@paragraphMarker='true'][1]/
             preceding-sibling::node())
         ]"/>  
        </p>
    </xsl:for-each>
</xsl:template>

<xsl:template match="section">
    <xsl:select value-of="."/>
</xsl:template>

这不是不工作,我一直坚持下去。它为所有组选择了太多“部分”节点。任何帮助将不胜感激!

In XSL 1.0, I have had a search and have found similar items around grouping but I think this is slightly different. Apologies if this has already been covered I haven't been able to find the answer

Input

<?xml version="1.0"?>
<xmldoc>
<section paragraphMarker="true">Part 1. </section>
<section paragraphMarker="false">Part 2. </section>
<section paragraphMarker="false">Part 3. </section>
<section paragraphMarker="true">Part 4. </section>
<section paragraphMarker="true">Part 5. </section>
<section paragraphMarker="false">Part 6. </section>
</xmldoc>

Desired Output

<p>Part 1. Part 2. Part 3.</p>
<p>Part 4. </p>
<p>Part 5. Part 6. </p>

I have tried the following:-

<xsl:key name="sectionsWithParagraphMarker" 
    match="section[@paragraphMarker='true']" use="."/>

<xsl:template match="/">
<xsl:for-each select=
    "/xmldoc/section[generate-id()
         = 
    generate-id(key('sectionsWithParagraphMarker',.)[1])]">
   <p>
<xsl:apply-templates select="."/>
<xsl:apply-templates select="./following-sibling::node()
         [count(. | /xmldoc/section[@paragraphMarker='true'][1]/
             preceding-sibling::node())
         =
         count(/xmldoc/section[@paragraphMarker='true'][1]/
             preceding-sibling::node())
         ]"/>  
        </p>
    </xsl:for-each>
</xsl:template>

<xsl:template match="section">
    <xsl:select value-of="."/>
</xsl:template>

This isn't working and I have got stuck with it. It's selecting too many 'section' nodes for all groups. Any help would be gratefully received!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

唠甜嗑 2024-11-07 09:20:19
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
    <xsl:output omit-xml-declaration="yes" indent="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:template match="section">
        <xsl:if test="@paragraphMarker='true'">
            <p>
                <xsl:apply-templates select="." mode="text" />
            </p>
        </xsl:if>
    </xsl:template>

    <xsl:template match="section" mode="text">
        <xsl:value-of select="." />
        <xsl:apply-templates select="following-sibling::section[1][@paragraphMarker='false']" mode="text" />
    </xsl:template>
</xsl:stylesheet>

由于此代码仅向前查看,因此它比执行回溯的解决方案要高效得多(在许多实现中,向后移动的 XPath 轴速度很慢)。

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
    <xsl:output omit-xml-declaration="yes" indent="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:template match="section">
        <xsl:if test="@paragraphMarker='true'">
            <p>
                <xsl:apply-templates select="." mode="text" />
            </p>
        </xsl:if>
    </xsl:template>

    <xsl:template match="section" mode="text">
        <xsl:value-of select="." />
        <xsl:apply-templates select="following-sibling::section[1][@paragraphMarker='false']" mode="text" />
    </xsl:template>
</xsl:stylesheet>

Since this code only looks forward, it is much more efficient than a solution doing backtracking (the XPath axes which are going backwards are slow in many implementations).

撩发小公举 2024-11-07 09:20:19

此转换

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:key name="kSectsByPara"
  match="section[not(@paragraphMarker='true')]"
  use="generate-id(preceding-sibling::*
                    [@paragraphMarker='true']
                    [1]
                   )"
 />

 <xsl:template match="*[@paragraphMarker='true']">
  <p>
   <xsl:copy-of select=
    "text()|key('kSectsByPara', generate-id())/text()"/>
  </p>
 </xsl:template>

 <xsl:template match="*/*[not(@paragraphMarker='true')]"/>
</xsl:stylesheet>

应用于提供的 XML 文档时

<xmldoc>
    <section paragraphMarker="true">Part 1. </section>
    <section paragraphMarker="false">Part 2. </section>
    <section paragraphMarker="false">Part 3. </section>
    <section paragraphMarker="true">Part 4. </section>
    <section paragraphMarker="true">Part 5. </section>
    <section paragraphMarker="false">Part 6. </section>
</xmldoc>

产生所需的正确结果

<p>Part 1. Part 2. Part 3. </p>
<p>Part 4. </p>
<p>Part 5. Part 6. </p>

说明

<名为“kSectsByPara”的 code>定义了具有属性 paragraphMarker= 的 sectiongenerate-id() 之间的映射"true" 以及具有属性 paragraphMarker="false" 的以下 section 元素组。

This transformation:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:key name="kSectsByPara"
  match="section[not(@paragraphMarker='true')]"
  use="generate-id(preceding-sibling::*
                    [@paragraphMarker='true']
                    [1]
                   )"
 />

 <xsl:template match="*[@paragraphMarker='true']">
  <p>
   <xsl:copy-of select=
    "text()|key('kSectsByPara', generate-id())/text()"/>
  </p>
 </xsl:template>

 <xsl:template match="*/*[not(@paragraphMarker='true')]"/>
</xsl:stylesheet>

when applied on the provided XML document:

<xmldoc>
    <section paragraphMarker="true">Part 1. </section>
    <section paragraphMarker="false">Part 2. </section>
    <section paragraphMarker="false">Part 3. </section>
    <section paragraphMarker="true">Part 4. </section>
    <section paragraphMarker="true">Part 5. </section>
    <section paragraphMarker="false">Part 6. </section>
</xmldoc>

produces the wanted, correct result:

<p>Part 1. Part 2. Part 3. </p>
<p>Part 4. </p>
<p>Part 5. Part 6. </p>

Explanation:

The <xsl:key> named "kSectsByPara" defines the mapping between a generate-id() of a section having attribute paragraphMarker="true" and the group of following section elements that have their attribute paragraphMarker="false" .

好久不见√ 2024-11-07 09:20:19

以下样式表:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="section[@paragraphMarker='true']">
        <p>
            <xsl:apply-templates
               select=".|following-sibling::section[not(@paragraphMarker='true')]
           [preceding-sibling::section[@paragraphMarker='true'][1]=current()]" 
               mode="inner"/>
        </p>
    </xsl:template>
    <xsl:template match="section" />
</xsl:stylesheet>

产生所需的输出:

<p>Part 1. Part 2. Part 3. </p>
<p>Part 4. </p>
<p>Part 5. Part 6. </p>

在英语中,我们选择以下所有不是段落标记的同级,并且其第一个前面的同级段落标记是当前 标记。请注意,这要求我们遍历所有以下同级,然后回溯以查找前一个标记(在每种情况下)。

The following stylesheet:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="section[@paragraphMarker='true']">
        <p>
            <xsl:apply-templates
               select=".|following-sibling::section[not(@paragraphMarker='true')]
           [preceding-sibling::section[@paragraphMarker='true'][1]=current()]" 
               mode="inner"/>
        </p>
    </xsl:template>
    <xsl:template match="section" />
</xsl:stylesheet>

Produces the desired output:

<p>Part 1. Part 2. Part 3. </p>
<p>Part 4. </p>
<p>Part 5. Part 6. </p>

In English, we're selecting all of the following siblings that are not a paragraph marker and whose first preceding sibling that is a paragraph marker is the current marker. Note that this requires us to move through all of the following siblings and then backtrack to look for the previous marker (in each case).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文