如何使用 XSLT 2.0 根据字符串中的整数检索节点?

发布于 2024-12-04 22:18:59 字数 4415 浏览 2 评论 0原文

这是我的 XML 文档:

<w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
    <w:body>
        <w:p>
            <w:ppr>
                <w:pstyle w:val="Heading1" />
            </w:ppr>
            <w:r>
                <w:t>Para1</w:t>
            </w:r>
        </w:p>
        <w:p>
            <w:ppr>
                <w:pstyle w:val="Heading2" />
            </w:ppr>
            <w:r>
                <w:t>Para2</w:t>
            </w:r>
        </w:p>
        <w:p>
            <w:ppr>
                <w:pstyle w:val="Heading3" />
            </w:ppr>
            <w:r>
                <w:t>Para3</w:t>
            </w:r>
        </w:p>
        <w:p>
            <w:ppr>
                <w:pstyle w:val="Heading4" />
            </w:ppr>
            <w:r>
                <w:t>Para4</w:t>
            </w:r>
        </w:p>
        <w:p>
            <w:ppr>
                <w:pstyle w:val="Heading1" />
            </w:ppr>
            <w:r>
                <w:t>Para5</w:t>
            </w:r>
        </w:p>
        <w:p>
            <w:ppr>
                <w:pstyle w:val="Heading3" />
            </w:ppr>
            <w:r>
                <w:t>Para6</w:t>
            </w:r>
        </w:p>
        <w:p>
            <w:ppr>
                <w:pstyle w:val="Heading4" />
            </w:ppr>
            <w:r>
                <w:t>Para7</w:t>
            </w:r>
        </w:p>
        <w:p>
            <w:ppr>
                <w:pstyle w:val="Heading2" />
            </w:ppr>
            <w:r>
                <w:t>Para8</w:t>
            </w:r>
        </w:p>
        <!-- This is my Current Node -->
        <w:p>
            <w:ppr>
                <w:pstyle w:val="Heading3" />
            </w:ppr>
            <w:r>
                <w:t>Para9</w:t>
            </w:r>
        </w:p>
        <w:p>
            <w:ppr>
                <w:pstyle w:val="Heading1" />
            </w:ppr>
            <w:r>
                <w:t>Para10</w:t>
            </w:r>
        </w:p>
    </w:body>
</w:document>

因此,在读取每个元素时,我想检查 w:ppr/w:pstyle 的属性 w:val。例如,在上面的文件中,第一个 w:p 包含 (w:ppr/w:pstyle/@w:val) 属性值作为 Heading1。所以,对于第一个w:p,我什么都不关心,只是接受它。之后,采用此 w:p

  1. 我想拆分属性值 Heading1 以检索标题后的字符串。所以,现在我们得到1。然后,在读取下一个 w:p 时,应用相同的逻辑来拆分当前属性值。因此,在本例中,我们有 2。现在,我想将当前值 2 与之前的值 1 进行比较。
  2. 如果它小于先前的值,则仅选择当前的w:p。否则,不要做任何事情。

对所有 w:p 节点应用上述步骤 1 和 2。因此,就我而言,我只想选择以下 w:p 节点。

示例输出节点为(完全获取整个 w:p 节点):

<w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
    <w:body>
        <w:p>
            <w:ppr>
                <w:pstyle w:val="Heading1" />
            </w:ppr>
            <w:r>
                <w:t>Para1</w:t>
            </w:r>
        </w:p>
        <w:p>
            <w:ppr>
                <w:pstyle w:val="Heading1" />
            </w:ppr>
            <w:r>
                <w:t>Para5</w:t>
            </w:r>
        </w:p>
        <w:p>
            <w:ppr>
                <w:pstyle w:val="Heading2" />
            </w:ppr>
            <w:r>
                <w:t>Para8</w:t>
            </w:r>
        </w:p>
        <w:p>
            <w:ppr>
                <w:pstyle w:val="Heading1" />
            </w:ppr>
            <w:r>
                <w:t>Para10</w:t>
            </w:r>
        </w:p>
    </w:body>
</w:document>

This is my XML document:

<w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
    <w:body>
        <w:p>
            <w:ppr>
                <w:pstyle w:val="Heading1" />
            </w:ppr>
            <w:r>
                <w:t>Para1</w:t>
            </w:r>
        </w:p>
        <w:p>
            <w:ppr>
                <w:pstyle w:val="Heading2" />
            </w:ppr>
            <w:r>
                <w:t>Para2</w:t>
            </w:r>
        </w:p>
        <w:p>
            <w:ppr>
                <w:pstyle w:val="Heading3" />
            </w:ppr>
            <w:r>
                <w:t>Para3</w:t>
            </w:r>
        </w:p>
        <w:p>
            <w:ppr>
                <w:pstyle w:val="Heading4" />
            </w:ppr>
            <w:r>
                <w:t>Para4</w:t>
            </w:r>
        </w:p>
        <w:p>
            <w:ppr>
                <w:pstyle w:val="Heading1" />
            </w:ppr>
            <w:r>
                <w:t>Para5</w:t>
            </w:r>
        </w:p>
        <w:p>
            <w:ppr>
                <w:pstyle w:val="Heading3" />
            </w:ppr>
            <w:r>
                <w:t>Para6</w:t>
            </w:r>
        </w:p>
        <w:p>
            <w:ppr>
                <w:pstyle w:val="Heading4" />
            </w:ppr>
            <w:r>
                <w:t>Para7</w:t>
            </w:r>
        </w:p>
        <w:p>
            <w:ppr>
                <w:pstyle w:val="Heading2" />
            </w:ppr>
            <w:r>
                <w:t>Para8</w:t>
            </w:r>
        </w:p>
        <!-- This is my Current Node -->
        <w:p>
            <w:ppr>
                <w:pstyle w:val="Heading3" />
            </w:ppr>
            <w:r>
                <w:t>Para9</w:t>
            </w:r>
        </w:p>
        <w:p>
            <w:ppr>
                <w:pstyle w:val="Heading1" />
            </w:ppr>
            <w:r>
                <w:t>Para10</w:t>
            </w:r>
        </w:p>
    </w:body>
</w:document>

So, while reading each element, I want to check the attribute w:val of w:ppr/w:pstyle. For example, in the above file, the first w:p contains that (w:ppr/w:pstyle/@w:val) attribute value as Heading1. So, For the first w:p, i don't care about anything and just take it. After, taken this w:p:

  1. I want to split the attribute value Heading1 for retrieving strings after the Heading. So, Now we get 1. Afterwards, while reading the next w:p, apply the same logic for splitting the current attribute value. So, in this case, we have 2. Now, I want to compare this current value 2 with previous value 1.
  2. If it is less than the previous value then only select the current w:p. Otherwise, don't do anything.

Apply the above step 1 and 2 for all of the w:p nodes. So, In my case, I want to select, only the following w:p nodes.

Sample output nodes are (getting whole w:p node completely):

<w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
    <w:body>
        <w:p>
            <w:ppr>
                <w:pstyle w:val="Heading1" />
            </w:ppr>
            <w:r>
                <w:t>Para1</w:t>
            </w:r>
        </w:p>
        <w:p>
            <w:ppr>
                <w:pstyle w:val="Heading1" />
            </w:ppr>
            <w:r>
                <w:t>Para5</w:t>
            </w:r>
        </w:p>
        <w:p>
            <w:ppr>
                <w:pstyle w:val="Heading2" />
            </w:ppr>
            <w:r>
                <w:t>Para8</w:t>
            </w:r>
        </w:p>
        <w:p>
            <w:ppr>
                <w:pstyle w:val="Heading1" />
            </w:ppr>
            <w:r>
                <w:t>Para10</w:t>
            </w:r>
        </w:p>
    </w:body>
</w:document>

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

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

发布评论

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

评论(1

栖竹 2024-12-11 22:18:59

我相信您的意思是,当相关的 w:val 属性大于 w:val 时,您希望忽略 w:p 节点> 前一个 w:p 元素(如果存在)。

在 XPath 术语中,其中...

number(substring-after(w:ppr/w:pstyle/@w:val, 'Heading'))
>= number(substring-after(preceding-sibling::w:p[1]/w:ppr/w:pstyle/@w:val, 'Heading'))  

这是完整的 XSLT,它是恒等变换,具有额外的情况来匹配此类 w:p 节点并忽略它们:

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

   <xsl:template match="/">
      <xsl:apply-templates />
   </xsl:template>

   <xsl:template match="w:p
   [
      preceding-sibling::w:p[1] 
      and 
         number(substring-after(w:ppr/w:pstyle/@w:val, 'Heading')) 
         >= number(substring-after(preceding-sibling::w:p[1]/w:ppr/w:pstyle/@w:val, 'Heading'))   
   ]">
   </xsl:template>

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

   <xsl:template match="comment()" />
</xsl:stylesheet>

当应用于输入样本时,生成以下输出:

<w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
   <w:body>
      <w:p>
         <w:ppr>
            <w:pstyle w:val="Heading1"/>
         </w:ppr>
         <w:r>
            <w:t>Para1</w:t>
         </w:r>
      </w:p>
      <w:p>
         <w:ppr>
            <w:pstyle w:val="Heading1"/>
         </w:ppr>
         <w:r>
            <w:t>Para5</w:t>
         </w:r>
      </w:p>
      <w:p>
         <w:ppr>
            <w:pstyle w:val="Heading2"/>
         </w:ppr>
         <w:r>
            <w:t>Para8</w:t>
         </w:r>
      </w:p>
      <w:p>
         <w:ppr>
            <w:pstyle w:val="Heading1"/>
         </w:ppr>
         <w:r>
            <w:t>Para10</w:t>
         </w:r>
      </w:p>
   </w:body>
</w:document>

I believe what you are saying is that you wish to ignore w:p nodes when the relevant w:val attribute is greater than the w:val element of the previous w:p (where it exists).

In XPath terms, where...

number(substring-after(w:ppr/w:pstyle/@w:val, 'Heading'))
>= number(substring-after(preceding-sibling::w:p[1]/w:ppr/w:pstyle/@w:val, 'Heading'))  

Here is the full XSLT, which is the identity transform, with the extra case to match such w:p nodes and ignore thems:

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

   <xsl:template match="/">
      <xsl:apply-templates />
   </xsl:template>

   <xsl:template match="w:p
   [
      preceding-sibling::w:p[1] 
      and 
         number(substring-after(w:ppr/w:pstyle/@w:val, 'Heading')) 
         >= number(substring-after(preceding-sibling::w:p[1]/w:ppr/w:pstyle/@w:val, 'Heading'))   
   ]">
   </xsl:template>

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

   <xsl:template match="comment()" />
</xsl:stylesheet>

When applied to your input sample, the following output is generated:

<w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
   <w:body>
      <w:p>
         <w:ppr>
            <w:pstyle w:val="Heading1"/>
         </w:ppr>
         <w:r>
            <w:t>Para1</w:t>
         </w:r>
      </w:p>
      <w:p>
         <w:ppr>
            <w:pstyle w:val="Heading1"/>
         </w:ppr>
         <w:r>
            <w:t>Para5</w:t>
         </w:r>
      </w:p>
      <w:p>
         <w:ppr>
            <w:pstyle w:val="Heading2"/>
         </w:ppr>
         <w:r>
            <w:t>Para8</w:t>
         </w:r>
      </w:p>
      <w:p>
         <w:ppr>
            <w:pstyle w:val="Heading1"/>
         </w:ppr>
         <w:r>
            <w:t>Para10</w:t>
         </w:r>
      </w:p>
   </w:body>
</w:document>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文