【问题标题】:XSLT 2.0, Xpath, DITA: Select all content between two elements of same nameXSLT 2.0、Xpath、DITA:选择两个同名元素之间的所有内容
【发布时间】:2015-10-08 21:20:08
【问题描述】:

我正在获取一个平面 HTML 源并将其转换为分层 DITA 文件s,以及它们关联的 .ditamap

它是fiddled,但当然,<result-document> 在那里不起作用。

编辑:refiddled 是对问题的更小更简洁的反映。

我很接近。这代表了我的来源。它看起来很复杂,但实际上并非如此:结果文档将是 <concept> 元素之间的所有内容......无论其中的嵌套/复杂性如何。

<!--
     this is an interim file while converting flat html
     to a hierarchical DITA structure
  -->
  <concepts text-title="Manual" id="manual">
     <concept id="chapter1">
        <title>Chapter 1</title>
        <conbody>
           <p>contents in body will</p>
           <lq><i>vary</i> widely</lq>
           <concept id="subchapter1-1">
              <title>Subchapter 1</title>
              <conbody>
                 <table>table</table>
                 <lq>foo</lq>
              </conbody>            
           </concept>
        </conbody>
     </concept>
     <concept id="chapter2">
        <title>Chapter 2</title>
        <conbody>
           <table>table</table>
           <lq>foo <pre>code</pre></lq>
        </conbody>
        <concept id="subchapter2-1">
           <title>Subchapter 1</title>
           <conbody>
              <table>table</table>
              <lq><b>foo</b></lq>
           </conbody>            
        </concept>            
     </concept>         
  </concepts>

这是我的xslt,我在困难的地方做了cmets。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs mf"
xmlns:mf="http://example.org/mf"                
version="2.0">

<xsl:output
    method="xml"
    omit-xml-declaration="no"
    doctype-system="../dtd/technicalContent/dtd/map.dtd" 
    doctype-public="-//OASIS//DTD DITA Map//EN"
    encoding="UTF-8"
    indent="yes"/>    
<xsl:strip-space elements="*"/>

<!--
    Source: monolithic XML file containing many nested <concept> topics
    Transform outcomes:
        1. Transform of source will create a DITA <map><topicref>
        2. A <result-document> will write out each <concept> as a singular file       
-->

<xsl:template match="/">
    <map 
        title="{/concepts/@text-title}"
        id="{/concepts/@id}">
        <xsl:apply-templates/> 
    </map>
</xsl:template>

<xsl:template match="text()"/>

<xsl:template match="concepts">
    <xsl:apply-templates/>
</xsl:template>

<xsl:template match="concept">

    <xsl:variable name="path-filename" select="concat('/home/mike/dita/prodrun/',@id,'.dita')"/>
    <!-- transform source to make the DITA <map> -->
    <topicref href="{$path-filename}" type="concept">
        <xsl:apply-templates/>
    </topicref>

    <!-- write out this <concept> to the file system -->
    <xsl:result-document
        method="xml"
        encoding="UTF-8"
        omit-xml-declaration="no"
        indent="yes"
        doctype-system="../../dtd/technicalContent/dtd/concept.dtd" 
        doctype-public="-//OASIS//DTD DITA Concept//EN"            
        href="{$path-filename}">
        <concept id="new foo will be added here">
            <!-- 
                Below is one of my efforts. I need to select ALL, to stopping short of next <concept>
                I also tried <for-each-group's .. to no avail
            -->
            <xsl:copy-of select="descendant::*[not(self::*)][preceding::concept[1]]"/>    
        </concept>
    </xsl:result-document>

</xsl:template>

最后,我会得到ditamap,这部分有效。我的文件系统中也会有四个这样的文件:

 <concept id="t20">
     <title>Chapter 1</title>
     <conbody>
        <p>contents in body will</p>
        <lq><i>vary</i> widely</lq>
     </conbody>
  </concept>

  <concept id="subchapter1-1">
     <title>Subchapter 1</title>
     <conbody>
        <table>table</table>
        <lq>foo</lq>
     </conbody>            
  </concept>

  <concept id="chapter2">
     <title>Chapter 2</title>
     <conbody>
        <table>table</table>
        <lq>foo <pre>code</pre></lq>
     </conbody>
  </concept>

  <concept id="subchapter2-1">
     <title>Subchapter 1</title>
     <conbody>
        <table>table</table>
        <lq><b>foo</b></lq>
     </conbody>            
  </concept>            

FWIW:我正在使用 OxygenXML,但我将在命令行中使用 Saxon 例行运行它。

旁注:这让我对文档类型、命名空间和动态验证的实用性大开眼界。

【问题讨论】:

    标签: xpath xslt-2.0 dita


    【解决方案1】:

    试试这个,必须做的工作而不是这个;)

    <!--concept id="new foo will be added here"-->
            <concept>
                <xsl:attribute name="id"><xsl:value-of select="@id"/></xsl:attribute>
                <title>
                    <xsl:copy-of select="title/@*|title/node()"/>    
                </title>
                <conbody>
                    <xsl:copy-of select="conbody/@*|conbody/node()"/>    
                </conbody>
                <!-- 
                Below is one of my efforts. I need to select ALL, to stopping short of next <concept>
                I also tried <for-each-group's .. to no avail
            -->
    
                <!--xsl:copy-of select="descendant::*[not(self::*)][preceding::concept[1]]"/-->    
            </concept>
    

    【讨论】:

    • 试过了。它过头了。 (即,它将第 1 小节拉到第 1 章中)。
    • 现在怎么样?请注意,您的第 1 章没有遵循 DITA DTD(它在 conbody 内部有概念),但根据我的测试,这现在应该可以工作了......我希望。
    【解决方案2】:

    到目前为止我所拥有的(演示的简化源,fiddled)。它似乎有效。

    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="xs"
    version="2.0">
    
    <xsl:output
        method="xml"
        omit-xml-declaration="yes"
        encoding="UTF-8"
        indent="yes"/>    
    <xsl:strip-space elements="*"/>
    
    <xsl:template match="node()|@*">    
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>
    
    <xsl:template match="/">
        <xsl:apply-templates/> 
    </xsl:template>
    
    <xsl:template match="concept"/>
    
    <!-- 
        The xpath in the <for-each> below:
        ..give me the descendants of this <concept>..
        ..excluding descendants that may be in 
        descendant 'nested' <concept>'s
    -->
    
    <xsl:template match="concepts">
        <documents>
            <xsl:for-each select="//concept">
                <simulated-result-document>
                    <xsl:for-each 
                        select="node() | text()
                        [descendant::*]                    
                        [not(descendant::concept[self::concept])]"> 
                        <xsl:apply-templates select="."/>
                    </xsl:for-each>
                </simulated-result-document>        
            </xsl:for-each>
        </documents>
    </xsl:template>
    

    源 XML:

       <concepts>
      <concept id="1">
         <title>Title 1 - General</title>
         Test unbound text here. 
         <p>In determining the..</p>
         <p>Words describing the singular..</p>
         <p>Words describing the plural..</p>      
         <concept id="2">
            <title>Chapter 2 - Rules</title>
            <p>Words implying the masculine gender..</p>
            <p>Words implying the feminine..</p>
            <p>words in the present tense..</p>
            <concept id="3">
               <title>§ 1. Gender</title>
               <p>Male.. text text text </p>
               <p>Female.. text text text </p>            
            </concept>
            <concept id="4">
               <title>§ 2. Jurisdiction</title>
               <p>Time.. jurisdiction text text text</p>
               <p>Place.. jurisdiction text text text</p>
               <p>Person.. jurisdiction text text text</p>
               <concept id="4.1">
                  <title>§ 2.1 Status</title>
                  <p>Citizen.. text text text </p>
                  <p>Stateless.. text text text </p>
               </concept>            
            </concept>
         </concept>
         <concept id="5">
            <title>Chapter 2 - Authority</title>
            <p>Time.. authority text text text</p>
            <p>Place.. authority text text text</p>         
            <concept id="6">
               <title>§ 1. Determination</title>
               <p>Time.. Universal Coordinated Time..<b>UTC</b></p>
               <p>Place.. Cartesian Coordinates</p>
            </concept>
            <concept id="7">
               <title>§ 2. Foo</title>
               <p>signatures convey..</p>
               <p>oath is ..</p>
               <p>utterances are ..</p>
            </concept>
         </concept>      
      </concept>
    

    注意事项:

    1. 我尝试通过轴定位来完成这一切,如果可以的话,我想避免使用@id

    2. OxygenXML 显示The descendant axis starting at a text node will never select anything 警告。网络小提琴没有。好奇。

    【讨论】:

      【解决方案3】:

      关于此备注:

      OxygenXML 显示从文本节点开始的后代轴将永远不会选择任何警告。网络小提琴没有。好奇。

      Oxygen 使用 Saxon XSLT 处理器验证 XSLT。这意味着只要 XSLT 样式表中的 XPath 包含如下内容:

      text()[后代::*]

      文本节点没有后代,所以 descendant::* 选择器不会选择任何东西。

      【讨论】:

        猜你喜欢
        • 2012-06-07
        • 1970-01-01
        • 1970-01-01
        • 2017-07-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多