我有一个输入XML,必须对其进行转换以将p标签和p标签与属性进行合并,但由于重复可能是动态的,因此无法对此有所了解。以及其余XML内容必须照原样复制
输入XML:
<Node1>
<head>first</head>
<body>Second</body>
<p>This is initial tag.</p>
<p merge="Y">Additional tag.</p>
<p merge="Y">Tag1.</p>
<p merge="Y">Tag2.</p>
<p merge="Y">Tag3.</p>
<p merge="Y">TagN.</p>
<tail>third</tail>
</Node1>
预期的输出XML:
<Node1>
<head>first</head>
<body>Second</body>
<p>This is initial tag.Additional tag.Tag1.Tag2.Tag3.TagN.</p>
<tail>third</tail>
</Node1>
p标签必须与具有merge =“ y”属性内容的p标签合并,并且可能存在多个带有merge =“ y”且重复次数为N的p标签。有没有办法,可以将其与XSL代码合并。
有人可以指导我吗?预先感谢。
答案 0 :(得分:0)
合并“初始” <p>
元素(无merge
属性='Y')
后跟<p>
个元素(带有merge
属性='Y'),则需要
匹配“ p”的模板。
在此模板内应有<xsl:if test="not(@merge = 'Y')">
,
只能提供 “初始”元素。
复制内容的说明应包括:
<p>
个兄弟姐妹之后跟随@merge = 'Y'
(谓词1),<p>
元素(谓词2),separator
(默认为空格)。这样,即使您有另一个“初始” <p>
元素,脚本也可以正常运行
与(另一个)以下<p>
个元素序列进行合并(如
我的示例如下)。
因此XSLT脚本可以如下:
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output method="xml" omit-xml-declaration="yes" encoding="UTF-8" indent="yes" />
<xsl:strip-space elements="*"/>
<xsl:template match="p">
<xsl:if test="not(@merge = 'Y')">
<xsl:copy>
<xsl:value-of select="., following-sibling::p[@merge = 'Y']
[generate-id(preceding-sibling::p[not(@merge = 'Y')][1])
= generate-id(current())]"
separator=""/>
</xsl:copy>
</xsl:if>
</xsl:template>
<xsl:template match="@*|node()">
<xsl:copy><xsl:apply-templates select="@*|node()"/></xsl:copy>
</xsl:template>
</xsl:transform>
有关工作示例,请参见http://xsltfiddle.liberty-development.net/gWmuiJZ
在 XSLT 1.0 中,需要进行一些更改,因为版本1.0中的value-of
以其他方式工作(并且不支持separtor
属性)。
为避免此问题,您应为{
当前元素和value-of
循环(另外一个for-each
)用于
跟随兄弟姐妹。
有关1.0版的示例,请参见http://xsltransform.net/3MEbY7K
答案 1 :(得分:0)
您可以尝试在前面的同级p merge="Y"
上键入p
元素:
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:strip-space elements="*"/>
<xsl:output indent="yes"/>
<xsl:key name="initial-p" match="p[@merge = 'Y']" use="generate-id(preceding-sibling::p[not(@merge = 'Y')][1])"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Node1/p[not(@merge = 'Y')]">
<xsl:copy>
<xsl:apply-templates select="node() | key('initial-p', generate-id())/node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Node1/p[@merge = 'Y']"/>
</xsl:stylesheet>
https://xsltfiddle.liberty-development.net/gWmuiK1
关于键的使用:样式表定义了键<xsl:key name="initial-p" match="p[@merge = 'Y']" use="generate-id(preceding-sibling::p[not(@merge = 'Y')][1])"/>
,这意味着XSLT处理器在先前的第一个同级p[@merge = 'Y']
的生成ID上索引p
元素,而没有该键merge
属性。然后,这些p
元素(即match="Node1/p[not(@merge = 'Y')]"
)的模板可以通过调用p[@merge = 'Y']
和{{ 1}}只是确保仅进一步处理那些元素的内容(这意味着在完整样式表的上下文中,内容由身份转换模板复制)。
您可以在任何XSLT教科书中找到有关使用键的更多信息,例如,在线https://cranesoftwrights.github.io/books/ptux/index.htm上的“使用XSLT和XPath进行实用转换”一书在第7章中有一个“ XSLT键节点引用”子节。 ,第4节。