XSLT 2.0,Xpath,DITA:选择两个同名元素之间的所有内容

时间:2015-10-08 21:20:09

标签: xpath xslt-2.0 dita

我正在使用平面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,我在困难的地方做了评论。

<?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一起运行。

Sidenote :这让我真正开始了解doctypes,命名空间和动态验证的实用性。

3 个答案:

答案 0 :(得分: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 :(得分:0)

到目前为止(演示的简化源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警告。网络小提琴没有。好奇。

答案 2 :(得分:0)

关于这句话:

  

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

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

  

文本()[后裔:: *]

文本节点没有后代,因此 descendant :: * 选择器不会选择任何内容。