使用xsl多次连接特定的XML标签元素内容

时间:2018-10-07 14:49:09

标签: xml xslt

我有一个输入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代码合并。

有人可以指导我吗?预先感谢。

2 个答案:

答案 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节。