2015-05-11 4 views
0

Я использую XSLT для преобразования XML-документов, содержащих сложную структуру данных, свободного текста и т. Д. В документ HTML. Документы, которые я обрабатываю, могут быть с конструктивными элементами или без них, и если существующие структурные теги могут быть вложены произвольно. Теги данных могут ссылаться на на любой тип товаров, поэтому я заранее не знаю содержание документа XML.Xsl Сохранение текстового порядка вывода

Документы выглядит

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<?xml-stylesheet type="text/xsl" href="my.xsl"?> 
<doc> 
    <elementStructure type="tag"> 
    The following items are cars: 
    <Car id="12" type="data" value="Ferrari"> this is a sport car. 
    <structureLev2 type="tag"> 
     <Model id="432" value="458" /> 
     <Rim id="55" value="wheels of car" type="data"> 
     <Tire id="234" value="front" type="data"> 
     <Note id="33" value="special tire" type="data"/> size of front is less that rear. 
     <TypeTire id="44" value="radial tire" type="data"/> 
     </Tire> 
    </Rim> 
    </structureLev2> 
    </Car> 
    </elementStructure> 
    <elementStructure type="tag"> 
    Other text 
    <Car id="22" type="data" value="Ford"> 
     this is a family car. 
     <structureLev2 type="tag"> 
     <Model id="872" value="Mondeo" /> 
     <Rim id="45" value="wheels of car" type="data"> 
      <Tire id="734" value="front" type="data"> 
      <Note id="63" value="normal tire" type="data"/> spare tire could be replaced by run-flat. 
      <TypeTire id="84" value="tubeless tire" type="data"/> 
      </Tire> 
     </Rim> 
    </structureLev2> 
    </Car> 
    </elementStructure> 
</doc> 

Desiderata HTML документ должен выглядеть примерно так:

<section> 
Some text.... 
<ul>  
    <li>Car - Ferrari (this is a sport car.)</li> 
    <li>Rim - wheels of the car:</li> 
    <ul> 
    <li>Tire - front Note: special tire (size of front is less than rear).</li> 
    <li>TypeTire - radial tire 
    </ul> 
</ul> 
</section> 

На самом деле я не знаю, если это хорошее решение, но так как я не знаю, если мой xml содержит или не структурные теги, я использовал «переключатель» для выбора между двумя основными шаблонами.

<?xml version="1.0"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
<xsl:output method="html"/> 
<xsl:strip-space elements="*"/> 
<xsl:template match="doc"> 
<html> 
    <body> 
    <xsl:choose> 
    <xsl:when test="//*[@type='tag']"> 
     <xsl:call-template name="stuct" /> 
    </xsl:when> 
    <xsl:otherwise> 
     <xsl:call-template name="plain" /> 
    </xsl:otherwise> 
    </xsl:choose> 
    </body> 
</html> 
</xsl:template> 
<xsl:template match="doc/*[@type='tag']" name="stuct"> 
    <h3> 
    <xsl:value-of select="text()"/> 
    </h3> 
    <xsl:apply-templates mode="str"/> 
</xsl:template> 
<xsl:template match="doc/*[@type='tag']" mode="str"> 
    <ul> 
    <li> 
    <xsl:call-template name="dataElem"/> 
    <xsl:apply-templates mode="str"/> 
    </li> 
    </ul> 
</xsl:template> 
<xsl:template match="doc/*[@type='data']" name="dataElem"> 
    <xsl:for-each select="descendant::node()[not(@type='tag')]"> 
    <xsl:value-of select="name(.)"/>: <xsl:value-of select="@value" /> (<xsl:value-of select="text()"/>)<br/> 
    </xsl:for-each> 
</xsl:template> 
<xsl:template match="doc/*[@type='data']" name="plain"> 
    <xsl:call-template name="dataElem" /> 
    </xsl:template> 
</xsl:stylesheet> 

Среди всех проблем, которые я получил, начиная с самого кода :-) одна проблема, которая возникает о тексте. Я хочу, чтобы текст между тегами мог появляться только один раз, а после «проанализированного» элемента. Является ли это возможным?

ответ

0

Трудно определить логику требуемого преобразования из одного неполного примера. Более того, я подозреваю, что предоставленная продукция на самом деле неверна - поскольку нет никаких очевидных оснований для того, чтобы продвигать «обод» в качестве брата «Автомобиль», когда в оригинальном документе это его ребенок.

Возможно, что-то вроде этого может работать для вас:

XSLT 1,0

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

<xsl:template match="/"> 
    <html> 
     <body> 
      <xsl:apply-templates select="*"/> 
     </body> 
    </html> 
</xsl:template> 

<xsl:template match="elementStructure"> 
    <section> 
     <xsl:value-of select="normalize-space(text())"/> 
     <ul> 
      <xsl:apply-templates select="*"/> 
     </ul> 
    </section> 
</xsl:template> 

<xsl:template match="*[@type='data']"> 
    <li> 
     <xsl:value-of select="concat(name(), ' - ', @value)"/> 
     <xsl:if test="text()"> 
      <xsl:value-of select="concat(' (', normalize-space(text()), ')')"/> 
     </xsl:if> 
     <xsl:if test="descendant::*[@type='data']"> 
      <ul> 
       <xsl:apply-templates select="*"/> 
      </ul> 
     </xsl:if> 
    </li> 
</xsl:template> 

</xsl:stylesheet> 

При нанесении на вашем примере входа, результат будет:

<html> 
    <body> 
     <section>The following items are cars: 
     <ul> 
      <li>Car - Ferrari (this is a sport car.) 
       <ul> 
        <li>Rim - wheels of car 
        <ul> 
         <li>Tire - front (size of front is less that rear.) 
          <ul> 
           <li>Note - special tire</li> 
           <li>TypeTire - radial tire</li> 
          </ul> 
         </li> 
        </ul> 
        </li> 
       </ul> 
      </li> 
     </ul> 
     </section> 
     <section>Other text 
     <ul> 
      <li>Car - Ford (this is a family car.) 
       <ul> 
        <li>Rim - wheels of car 
        <ul> 
         <li>Tire - front (spare tire could be replaced by run-flat.) 
          <ul> 
           <li>Note - normal tire</li> 
           <li>TypeTire - tubeless tire</li> 
          </ul> 
         </li> 
        </ul> 
        </li> 
       </ul> 
      </li> 
     </ul> 
     </section> 
    </body> 
</html> 

визуализируется как:

enter image description here

+0

Это именно то, что мне нужно! Отлично. Да, мой результат был неправильным. Я теряюсь с применением шаблонов. Благодаря! – user1732337