2

下面提到的内容是我的 XML 文档。

<w:document>

    <w:body>
             <w:p pStyle="Heading1">Para1</w:p> 
             <w:p pStyle="Heading2">Para2</w:p> 
             <w:p pStyle="Heading3">Para3</w:p> 
             <w:p pStyle="Heading4">Para4</w:p> 

             <w:p pStyle="Heading1">Para5</w:p> 
             <w:p pStyle="Heading3">Para6</w:p> 
             <w:p pStyle="Heading4">Para7</w:p> 

             <w:p pStyle="Heading2">Para8</w:p> 
             <w:p pStyle="Heading3">Para9</w:p> 

             <w:p pStyle="Heading1">Para10</w:p> 


    </w:body>

</w:document>

所以,在阅读每一个<w:p>时,我想检查它的属性值 pStyle 值。例如,在上面的文件中,第一个<w:p>包含该属性值作为“Heading1”。所以,首先<w:p>,我什么都不在乎,就拿它。之后,拿了这个<w:p>

*逻辑 1: *我想拆分属性值Heading1以在Heading之后检索字符串。所以,现在我们得到'1'

之后,在阅读下一个<w:p>时,应用相同的逻辑 1来吐出当前属性值。所以,在这种情况下,我们有'2'。现在,我想将此当前值'2'与先前值'1'进行比较。

逻辑2:如果小于前一个值则只选择当前值<w:p>,否则什么都不做。

对所有节点应用上述逻辑 1 和逻辑 2 。<w:p>

所以,就我而言,我只想选择以下<w:p>节点。

要求的选择是:

Para1
Para5
Para8
Para10

希望你明白我的问题...

这种情况我该怎么办?...

请指导我摆脱这个问题......

谢谢和问候, P.SARAVANAN

4

2 回答 2

3

我认为这可以在 XSLT1.0 中通过简单地添加到身份转换来完成。我认为,您只需要忽略pStyle属性大于或等于前一个兄弟的w:p节点。

<xsl:template match="w:p[
       number(substring-after(@pStyle, 'Heading')) 
       &gt;= number(substring-after(preceding-sibling::w:p[1]/@pStyle, 'Heading'))
    ]">
   <!-- Ignore the node -->
</xsl:template>

这是这种情况下的完整转换(请注意,您可能必须修改命名空间)

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

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

   <xsl:template match="w:p[number(substring-after(@pStyle, 'Heading')) &gt;= number(substring-after(preceding-sibling::w:p[1]/@pStyle, 'Heading'))]">
       <!-- Ignore the node -->
   </xsl:template>

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

应用于示例 XML 时,输出 XML 如下所示:

<w:document xmlns:w="http://stackoverflow.com/users/452680/saravanan">
   <w:body>
      <w:p pStyle="Heading1">Para1</w:p>
      <w:p pStyle="Heading1">Para5</w:p>
      <w:p pStyle="Heading2">Para8</w:p>
      <w:p pStyle="Heading1">Para10</w:p>
   </w:body>
</w:document>
于 2011-09-07T08:26:14.310 回答
2

只需使用这个 XPath 1.0 表达式

/*/*/w:p[not(substring-after(@pStyle,'Heading')
            >= 
             substring-after(preceding-sibling::*[1]/@pStyle,'Heading')
             )
         ]

选择同一组元素的相应 XPath 2.0 表达式是

 /*/*/w:p[1]
|
 /*/*/w:p[position() ge 2]
             [xs:integer(substring-after(@pStyle,'Heading'))
            lt
              xs:integer(substring-after(preceding-sibling::*[1]/@pStyle,'Heading'))
             ]

如果您使用 XSLT 2.0,您可以覆盖身份规则/模板,如下所示

<xsl:stylesheet version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:w="Undefined!!!">
    <xsl:output omit-xml-declaration="yes" indent="yes"/>
    <xsl:strip-space elements="*"/>

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

 <xsl:template match=
  "w:p[xs:integer(substring-after(@pStyle,'Heading'))
      ge
       xs:integer(substring-after(preceding-sibling::*[1]/@pStyle,'Heading'))
       ]"/>
</xsl:stylesheet>

当应用于提供的 XML 文档时(固定为格式正确):

<w:document xmlns:w="Undefined!!!">
    <w:body>
        <w:p pStyle="Heading1">Para1</w:p>
        <w:p pStyle="Heading2">Para2</w:p>
        <w:p pStyle="Heading3">Para3</w:p>
        <w:p pStyle="Heading4">Para4</w:p>
        <w:p pStyle="Heading1">Para5</w:p>
        <w:p pStyle="Heading3">Para6</w:p>
        <w:p pStyle="Heading4">Para7</w:p>
        <w:p pStyle="Heading2">Para8</w:p>
        <w:p pStyle="Heading3">Para9</w:p>
        <w:p pStyle="Heading1">Para10</w:p>
    </w:body>
</w:document>

产生了想要的正确结果

<w:document xmlns:w="Undefined!!!">
   <w:body>
      <w:p pStyle="Heading1">Para1</w:p>
      <w:p pStyle="Heading1">Para5</w:p>
      <w:p pStyle="Heading2">Para8</w:p>
      <w:p pStyle="Heading1">Para10</w:p>
   </w:body>
</w:document>

由于 XPath 1.0 缺乏强类型,因此覆盖标识规则的相应 XSLT 1.0 解决方案稍微简单一些:

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

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

     <xsl:template match=
      "w:p[substring-after(@pStyle,'Heading')
          >=
          substring-after(preceding-sibling::*[1]/@pStyle,'Heading')
           ]"/>
</xsl:stylesheet>

或者,您可以简单地使用此解决方案开头的表达式

XSLT 2.0:

<xsl:stylesheet version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:w="Undefined!!!" exclude-result-prefixes="xs">
    <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:template match="/">
<w:document xmlns:w="Undefined!!!">
    <w:body>
     <xsl:copy-of select=
    "/*/*/w:p[1]
      |
       /*/*/w:p[position() ge 2]
                 [xs:integer(substring-after(@pStyle,'Heading'))
               lt
                xs:integer(substring-after(preceding-sibling::*[1]/@pStyle,'Heading'))
               ]
      "/>
    </w:body>
 </w:document>
 </xsl:template>
</xsl:stylesheet>

XSLT 1.0:

<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:w="Undefined!!!">
    <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:template match="/">
<w:document xmlns:w="Undefined!!!">
    <w:body>
     <xsl:copy-of select=
    "/*/*/w:p
          [not(substring-after(@pStyle,'Heading')
              >=
               substring-after(preceding-sibling::*[1]/@pStyle,'Heading')
               )
          ]
      "/>
    </w:body>
 </w:document>
 </xsl:template>
</xsl:stylesheet>

所有上述三个 XSLT 转换都会产生所需的正确结果

于 2011-09-07T12:56:42.613 回答