【问题标题】:Creating parent-child elements from semantic hiearchy in element values in XSLT 2从 XSLT 2 中元素值中的语义层次结构创建父子元素
【发布时间】:2013-11-09 22:52:41
【问题描述】:

我在 XML 内容中有一系列 P 标记,它们的起始值具有语义层次结构,但是,P 标记是线性的。正在寻找 XSLT 2 转换。

语义层次如下:

(1)
 +-(a)
    +-(I)
       +-(A)

正则表达式序列如下:

<xsl:param name="patternOrder" as="element(pattern)*" xmlns="">
  <pattern level="1" value="^(\([0-9]+(\.[0-9]+)?\))" />
  <pattern level="2" value="^(\([a-z]\))" />
  <pattern level="3" value="^(\((IX|IV|V?I{{0,3}})\))" />
  <pattern level="4" value="^(\([\w]+(\.[\w]+)?\))" />
</xsl>

查看我的数据集后,我有各种情况:

<?xml version="1.0" encoding="UTF-8"?>
<test>
    <content>
        <p>(1) blah</p>
        <p>(2)(a) blah</p>
        <p>(b) blah</p>
        <p>(3)(a)(I) blah</p>
        <p>(II) blah</p>
        <p>(A) blah</p>
        <p>(B.1) blah</p>
        <p>(b) blah</p>
        <p>(4) blah</p>
        <p>(4.5) blah</p>
        <p>(5)(a)(I)(A) blah</p>
        <p>(B) blah</p>
        <p>(II) blah</p>
        <p>(III)(a) blah</p>
        <p>(bb.2) blah</p>
        <p>(6) blah</p>
    </content>
    <content>
        <p>blah</p>
    </content>
    <content>
        <p>blah</p>
        <p>(1) blah</p>
        <p>(a) blah</p>
        <p>(b) blah</p>
        <p>(2) blah </p>
    </content>
</test>

...最终结果应该是:

<?xml version="1.0" encoding="UTF-8"?>
<test>
    <content>
        <p>(1) blah</p>
        <p>(2)
            <p>(a) blah</p>
            <p>(b) blah</p>
        </p>
        <p>(3)
            <p>(a)
                <p>(I) blah</p>
                <p>(II) blah
                    <p>(A) blah</p>
                    <p>(B) blah</p>
                </p>
            </p>
            <p>(b) blah</p>
        </p>
        <p>(4) blah</p>
        <p>(4.5) blah</p>
        <p>(5)
            <p>(a)
                <p>(I)
                    <p>(A) blah</p>
                    <p>(B.1) blah</p>
                </p>      
                <p>(II) blah</p>
                <p>(III)</p>
                    <p>(a) blah</p>
                    <p>(bb.2) blah</p>
                </p>
            </p>
        <p>(6) blah</p>
    </content>
    <content>
        blah
    </content>
    <content>
        blah
        <p>(1) blah
            <p>(a) blah</p>
            <p>(b) blah</p>      
        </p>
        <p>(2) blah </p>
    </content>
</test>

如果语义层次不存在于 P 标签中,请注意条件 - 然后 P 标签被移除并且是其父内容元素的值。

编辑:

我已经能够使用以下 RegEx 检测到所有语义条件:

^(\(([\w]+(\.[\w]+)?)\)){1,4}

*编辑 #2 *

具有调平属性:

<?xml version="1.0" encoding="UTF-8"?>
<test>
    <content>
        <p level="1">(1) blah</p>
        <p level="1">(2)</p>
        <p level="2">(a) blah</p>
        <p level="2">(b) blah</p>
        <p level="1">(3)</p>
        <p level="2">(a)</p>
        <p level="3">(I) blah</p>
        <p level="3">(II) blah</p>
        <p level="4">(A) blah</p>
        <p level="4">(B.1) blah</p>
        <p level="2">(b) blah</p>
        <p level="1">(4) blah</p>
        <p level="1">(4.5) blah</p>
        <p level="1">(5)</p>
        <p level="2">(a)</p>
        <p level="3">(I)</p>
        <p level="4">(A) blah</p>
        <p level="4">(B) blah</p>
        <p level="3">(II) blah</p>
        <p level="3">(III)</p>
        <p level="2">(a) blah</p>
        <p level="2">(bb.2) blah</p>
        <p level="2">(6) blah</p>
    </content>
    <content>
        <p>blah</p>
    </content>
    <content>
        <p>blah</p>
        <p level="1">(1) blah</p>
        <p level="2">(a) blah</p>
        <p level="2">(b) blah</p>
        <p level="1">(2) blah </p>
    </content>
</test>

【问题讨论】:

    标签: xml xslt xslt-2.0


    【解决方案1】:

    第一阶段:改造

    <p>(2)(a) blah</p>
    <p>(b) blah</p>
    

    进入

    <p>(2)</p>
    <p>(a) blah</p>
    <p>(b) blah</p>
    

    使用类似的东西

    <xsl:template match="p">
      <xsl:for-each select="tokenize(., '\(')">
         <xsl:if test="normalize-space(.)">
           <p>(<xsl:value-of select="."/></p>
         </xsl:if>
      </xsl:for-each>
    </xsl:template>
    

    第二阶段:

    先写一个函数

    <xsl:function name="f:level" as="xs:integer">
      <xsl:param name="p" as="element(p)"/>
      ....
    </xsl:function>
    

    它根据匹配您的正则表达式计算“语义级别”。你似乎知道如何做这部分。

    然后写一个递归分组函数:

    <xsl:function name="f:group" as="element(p )*">
      <xsl:param name="in" as="element(p )*"/>
      <xsl:param name="level" as="xs:integer"/>
      <xsl:for-each-group select="$in" group-starting-with="p[f:level(.)=$level]">
        <p><xsl:value-of select="current-group()[1]"/>
          <xsl:sequence select="f:group(current-group()[position() gt 1], $level+1)"/>
        </p>
      </xsl:for-each-group>
    </xsl:function>
    

    并像这样调用这个函数:

    <xsl:template match="content">
      <xsl:sequence select="f:group(p, 1)"/>
    </xsl:template>
    

    未测试。

    【讨论】:

    • 弄清楚第 1 阶段 - 编辑了您的答案。现在要弄清楚如何为递归组函数消费做水平标记!
    • 想出了如何进行调平标记。然而,序列上的递归分组函数炸弹作为 0 参数函数返回。
    • 编辑了答案以(希望)修复此错误。
    • 那次编辑成功了!我已经为返回 f:group 的递归调用使用了各种参数——第二个参数为 $level+1,但无法确定当前组具有 [position() gt 1]。谢谢你!确实学到了很多东西。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-08-04
    • 2014-05-13
    • 2013-01-21
    • 1970-01-01
    • 2016-02-27
    • 1970-01-01
    • 2022-01-12
    相关资源
    最近更新 更多