下面提到的内容是我的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 Value。例如,在上面的文件中,第一个<w:p>
包含该属性值为“Heading1” 即可。所以,对于第一个<w:p>
,我不关心任何事情而只是接受它。之后,采取这个<w:p>
,
* 逻辑1: *我想拆分属性值标题1 ,以便在标题之后检索字符串。所以,现在我们得到'1'。
之后,在阅读下一个<w:p>
时,应用相同的 逻辑1 来实现当前属性值的吐出。所以,在这种情况下,我们有 '2'即可。现在,我想将此当前值'2'与之前的值'1'进行比较。
逻辑2: 如果它小于之前的值,则只选择当前的<w:p>
,否则,不要做任何事情。
为所有<w:p>
节点应用上述 逻辑1和逻辑2 。
所以,就我而言,我只想选择以下<w:p>
个节点。
必需的选择是:
Para1
Para5
Para8
Para10
希望你明白我的问题......
我为这种情况做了什么?...
请指导我摆脱这个问题...
谢谢&amp;问候, P.SARAVANAN
答案 0 :(得分:3)
我认为这可以通过对身份转换的简单补充在XSLT1.0中完成。你只需要忽略 w:p 节点,其中 pStyle 属性大于或等于前一个兄弟节点。我想。
<xsl:template match="w:p[
number(substring-after(@pStyle, 'Heading'))
>= 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')) >= 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>
答案 1 :(得分: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,则可以按以下方式覆盖identity rule/template :
<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转换都会产生想要的正确结果。