Xslt 如何解析特定的第一个子级<;日期线>;父标记的标记数据<;车身>;使用XSL 1.0并跳过输出中的值
从下面的示例输入和相应的输出中,我需要一个XSL转换来跳过父标记下第一次出现的Xslt 如何解析特定的第一个子级<;日期线>;父标记的标记数据<;车身>;使用XSL 1.0并跳过输出中的值,xslt,xslt-1.0,Xslt,Xslt 1.0,从下面的示例输入和相应的输出中,我需要一个XSL转换来跳过父标记下第一次出现的字段 <!--Given sample Input XML: --> <content> <data> <datatext> <message name="message">
字段
<!--Given sample Input XML: -->
<content>
<data>
<datatext>
<message name="message">
<p>Test message paragraph.
<dateline name="dateline">Message datelines</dateline>?
<annotation type="note">Test message Note.</annotation>
</p>
</message>
<head name="head">
<p>Test Head paragraph <annotation type="note">Head notes </annotation> paragraph.
<dateline name="dateline">Head dateline</dateline>
</p>
</head>
<body name="body">
<p>
Test first Body paragraph.
<annotation type="note">First Body notes.</annotation>
</p>
<p>Test Second Body paragraph.</p>
<p>
<annotation type="note">Second Body notes.</annotation>
Test third Body paragraph.
<dateline name="dateline">SECOND DATELINE</dateline>
</p>
<p>Test Fouth Body paragraph.</p>
<p>
<dateline name="dateline">THIRD DATELINE</dateline>
Test fourth Body paragraph.
<annotation type="note">Third Body notes.</annotation>
</p>
</body>
</datatext>
</data>
</content>
测试消息段落。
消息日期线?
测试消息注释。
测试标题段落标题注释段落。
首部日线
测试第一段正文。
第一个正文注释。
测试第二段正文
第二个正文注释。
测试第三段。
第二条日期线
测试第四段正文
第三条日期线
测试正文第四段。
第三个机构的说明。
预期输出,
标记的第一次出现应被删除
<!-- Expected Output XML -->
<content>
<data>
<datatext>
<message name="message">
<p>Test message paragraph.
<dateline name="dateline">Message datelines</dateline>?
<annotation type="note">Test message Note.</annotation>
</p>
</message>
<head name="head">
<p>Test Head paragraph <annotation type="note">Head notes </annotation> paragraph.
<dateline name="dateline">Head dateline</dateline>
</p>
</head>
<body name="body">
<p>
Test first Body paragraph.
<annotation type="note">First Body notes.</annotation>
</p>
<p>Test Second Body paragraph.</p>
<p>
<annotation type="note">Second Body notes.</annotation>
Test third Body paragraph.
</p>
<p>Test Fouth Body paragraph.</p>
<p>
<dateline name="dateline">THIRD DATELINE</dateline>
Test fourth Body paragraph.
<annotation type="note">Third Body notes.</annotation>
</p>
</body>
</datatext>
</data>
</content>
测试消息段落。
消息日期线?
测试消息注释。
测试标题段落标题注释段落。
首部日线
测试第一段正文。
第一个正文注释。
测试第二段正文
第二个正文注释。
测试第三段。
测试第四段正文
第三条日期线
测试正文第四段。
第三个机构的说明。
这里有一个可能的解决方案
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:variable name="bdl" select="//body//dateline"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="dateline[index-of($bdl,.) = 1]"/>
</xsl:stylesheet>
一开始我以为你只需要
<xsl:template match="//body//dateline[1]"/>
但这不起作用,因为[1]
谓词是焦点和上下文相关的,并且主体中的日期行
标记首先位于其直接父项下。此解决方案首先构建一个包含所有body日期行
标记的序列(在$bdl
中),然后仅删除与列表中第一个条目匹配的一个
可能有一种“更好”或更惯用的方法来实现这一点,我希望XSLT大师之一也会回答这个问题
仅跳过下中第一次出现的
字段
父标记
首先,body
是dateline
的祖先,而不是父方
现在,由于您希望复制除一个节点外的所有内容,因此最好从identity transform模板(复制所有内容)开始作为规则,并为相关节点添加一个例外:
XSLT1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<!-- identity transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="body//dateline[generate-id()=generate-id(ancestor::body/descendant::dateline[1])]"/>
</xsl:stylesheet>
而不是:
body//dateline[1]
下文对此进行了解释:
注意:位置路径//para[1]
与位置路径/genderant::para[1]
的含义不同。后者选择前者
后代para
元素;前者选择所有子体para
作为其父级的第一个子级的元素
然而,表达方式:
body/descendant::dateline[1]
body/descendant::dateline[1]
不是有效的匹配模式。尽管模式可以使用//运算符,但它们不能使用子体轴:
因此,我选择将任何
日期行
匹配为主体
的后代,并添加一个谓词,将当前日期行
的唯一id与祖先主体
的第一个后代
进行比较。这是因为谓词中允许使用子代轴。测试第一个正文段落。第一个正文注释。测试第二段正文。测试第三段正文。第二个正文注释。第三个日期行测试第四个正文段落。第三个机构的说明。这个问题被标记为xslt-1.0
。index-of()
函数需要XSLT 2.0。