2

我有一些(格式错误的 DITA)XML 格式如下:

<dl>
<dlentry><dt>BLARG</dt>
<dd>BLARG Definition</dd>
<dt>BLARG2</dt>
<dd>BLARG2 Definition</dd></dlentry>
</dl>
<dl>
<dlentry><dt>BLARG3</dt>
<dd>BLARG3 Definition</dd></dlentry>
</dl>
<p>Continuation of BLARG3 definition.</p>
<note>Note pertaining to BLARG3 definition</note>

等等。

我想做的是将这一系列<dl>元素合并为一个<dl>,如下所示:

<dl>
    <dlentry><dt>BLARG</dt>
       <dd>BLARG Definition</dd></dlentry>
    <dlentry><dt>BLARG2</dt>
       <dd>BLARG2 Definition</dd></dlentry>
    <dlentry><dt>BLARG3</dt>
       <dd>BLARG3 definition. Continuation of BLARG3 definition.
       <note>Note pertaining to BLARG3 definition</note></dd></dlentry>
<dl>

我正在尝试根据前面的值使用键来索引任何<p><note>节点,如下所示:generate-id()<dd>

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:key name="kFollowing" match="p|note|table" use="generate-id(preceding::dd[1])"/>
  <!-- identity template -->
<xsl:template match="@*|node()" name="identity">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
</xsl:template>
<xsl:template match="dl">
    <xsl:choose>
        <xsl:when test="count(preceding::dl)=0">
            <!--We only want to process the first dl. All others should be ignored, because their content will get included in this one.-->
            <dl>
                <!--Want to grab all following terms, except ones that contain phrase elements, which need to be turned into a table because they are field values-->
                <xsl:for-each select="following::dt[not(child::ph)]|descendant::dt">
                    <dlentry>
<dt><xsl:value-of select="normalize-space(.)"/></dt>
                        <xsl:variable name="ddID"><xsl:value-of select="generate-id(following::dd[1])"/></xsl:variable>
                        <dd><xsl:for-each select="following::dd[1]">
                            <xsl:apply-templates/><xsl:text>. </xsl:text>
                        </xsl:for-each>
                            <xsl:variable name="ddKey" select="key('kFollowing',generate-id(following::dd[1]))"/>
                            <xsl:for-each select="following::*[$ddKey]">
                               <xsl:apply-templates/>
</xsl:for-each>
                        </dd>
                    </dlentry>
                </xsl:for-each>
            </dl>   
        </xsl:when>
        <xsl:otherwise/>
    </xsl:choose>
</xsl:template>
4

2 回答 2

1
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes"/>
    <!-- using a test root -->
    <xsl:template match="/test">
        <dl>
            <xsl:apply-templates select="dl/*/dt" />
        </dl>
    </xsl:template>

    <!-- assuming that we have always a dd for each dt -->
    <xsl:template match="dt">
        <dlentry>
            <xsl:copy-of select="."/>
            <dd>
             <xsl:value-of select="following::*[1]"/>
             <!-- just check the node after dd or dlentry or dl -->
             <xsl:apply-templates select="following::*[2]
                [local-name()='p' or 
                 local-name()='note' or 
                 local-name()='table']"/>
            </dd>

        </dlentry>
    </xsl:template>

    <xsl:template match="p|note|table">
        <xsl:copy-of select="."/>
        <!-- copy next node only if wanted -->
        <xsl:apply-templates select="following::*[1]
                [local-name()='p' or 
                 local-name()='note' or 
                 local-name()='table']"/>
    </xsl:template>

</xsl:stylesheet>
于 2012-06-13T22:32:36.723 回答
1

这种转变

<xsl:stylesheet version="1.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     <xsl:output omit-xml-declaration="yes" indent="yes"/>
     <xsl:strip-space elements="*"/>

     <xsl:key name="kFollowing" match="p|note"
      use="generate-id(preceding-sibling::dl[1]/dlentry)"/>

     <xsl:template match="node()|@*">
         <xsl:copy>
           <xsl:apply-templates select="node()|@*"/>
         </xsl:copy>
     </xsl:template>

     <xsl:template match="dl[1]">
      <dl>
       <xsl:apply-templates select="../dl/dlentry"/>
      </dl>
     </xsl:template>

     <xsl:template match="dd">
      <dd>
        <xsl:value-of select="."/>
        <xsl:copy-of select="key('kFollowing', generate-id(..))/self::p/text()"/>
        <xsl:copy-of select="key('kFollowing', generate-id(..))/self::note"/>
      </dd>
     </xsl:template>
     <xsl:template match="dl|p|note"/>
</xsl:stylesheet>

当应用于以下 XML 文档时(提供的片段包装在单个顶部元素中):

<t>
    <dl>
        <dlentry>
            <dt>BLARG</dt>
            <dd>BLARG Definition</dd>
            <dt>BLARG2</dt>
            <dd>BLARG2 Definition</dd>
        </dlentry>
    </dl>
    <dl>
        <dlentry>
            <dt>BLARG3</dt>
            <dd>BLARG3 Definition</dd>
        </dlentry>
    </dl>
    <p>Continuation of BLARG3 definition.</p>
    <note>Note pertaining to BLARG3 definition</note>
</t>

产生想要的正确结果:

<t>
   <dl>
      <dlentry>
         <dt>BLARG</dt>
         <dd>BLARG Definition</dd>
         <dt>BLARG2</dt>
         <dd>BLARG2 Definition</dd>
      </dlentry>
      <dlentry>
         <dt>BLARG3</dt>
         <dd>BLARG3 DefinitionContinuation of BLARG3 definition.<note>Note pertaining to BLARG3 definition</note>
         </dd>
      </dlentry>
   </dl>
</t>

我故意没有". "在两个文本节点之间生成分隔符,因为这没有被声明为要求并且可能只是 OP 的装饰。这样做需要一点额外的努力,留给读者作为练习:)。

于 2012-06-14T02:18:13.963 回答