2013-03-05 3 views
0

Я пытаюсь преобразовать старые XML-файлы в новую и улучшенную структуру. Часть этого нужно мне, чтобы обернуть некоторые свободные элементы в родительский контейнер, а также изменять их детиИспользование XSLT для обертывания элементов, но он не включает последний элемент соответствия

Старая структура

<monograph> 
    <title>asdf</title> 

    <dosage.sec id="dosage.sec.1"> 
    <dosage.sec>asgfd</dosage.sec> 
    <dosage.sec>asgfd</dosage.sec> 
    </dosage.sec> 
    <dosage.sec id="dosage.sec.2"> 
    <dosage.sec>asgfd</dosage.sec> 
    <dosage.sec>asgfd</dosage.sec> 
    </dosage.sec> 
    <dosage.sec id="dosage.sec.3"> 
    <dosage.sec>asgfd</dosage.sec> 
    <dosage.sec>asgfd</dosage.sec> 
    </dosage.sec> 

    <products> 
    <prod>sadf</prod> 
    <prod>sadf</prod> 
    </products> 
</monograph> 

новая структура

<monograph> 
    <title>asdf</title> 

    <dosage> 
    <dosage.sec id="dosage.sec.1"> 
     <dosage.qual>asgfd</dosage.qual> 
     <dosage.qual>asgfd</dosage.qual> 
    </dosage.sec> 
    <dosage.sec id="dosage.sec.2"> 
     <dosage.qual>asgfd</dosage.qual> 
     <dosage.qual>asgfd</dosage.qual> 
    </dosage.sec> 
    <dosage.sec id="dosage.sec.3"> 
     <dosage.qual>asgfd</dosage.qual> 
     <dosage.qual>asgfd</dosage.qual> 
    </dosage.sec> 
    </dosage> 

    <products> 
    <prod>sadf</prod> 
    <prod>sadf</prod> 
    </products> 
</monograph> 

я нашел это answer и немного изменил его в соответствии с моими потребностями:

<!-- wrap dosage.sec elements in a dosage container --> 
<xsl:template match="node()|@*" name="dosage.sec"> 
    <xsl:copy> 
     <xsl:apply-templates select="node()|@*" /> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="monograph/dosage.sec[not(preceding-sibling::*[1][self::dosage.sec])]"> 
    <dosage> 
     <xsl:call-template name="dosage.sec" /> 
     <xsl:apply-templates mode="copy" select="following-sibling::*[1][self::dosage.sec]" /> 
    </dosage> 
</xsl:template> 

<xsl:template match="monograph/dosage.sec" mode="copy"> 
    <xsl:call-template name="dosage.sec"/> 
</xsl:template> 


<!-- rename children dosage.sec --> 
<xsl:template match="dosage.sec/dosage.sec"> 
    <dosage.qual> 
     <xsl:apply-templates /> 
    </dosage.qual> 
</xsl:template> 

Но мой вывод:

<monograph> 
    <title>asdf</title> 

    <dosage> 
    <dosage.sec id="dosage.sec.1"> 
     <dosage.qual>asgfd</dosage.qual> 
     <dosage.qual>asgfd</dosage.qual> 
    </dosage.sec> 
    <dosage.sec id="dosage.sec.2"> 
     <dosage.qual>asgfd</dosage.qual> 
     <dosage.qual>asgfd</dosage.qual> 
    </dosage.sec> 
    <dosage.sec id="dosage.sec.3"> 
     <dosage.qual>asgfd</dosage.qual> 
     <dosage.qual>asgfd</dosage.qual> 
    </dosage.sec> 
    </dosage> 

    <dosage.sec id="dosage.sec.3"> 
    <dosage.qual>asgfd</dosage.qual> 
    <dosage.qual>asgfd</dosage.qual> 
    </dosage.sec> 

    <products> 
    <prod>sadf</prod> 
    <prod>sadf</prod> 
    </products> 
</monograph> 

Я использую PHP5 встроенный объект XSLTProcessor - все XML и XSL являются версии 1.0

+0

Ваш XSLT вероятно, будет работать, если вы удалили '[1]' из строки: '', но способ, которым вы собираетесь, может быть не лучшим подходом. – JLRishe

+0

Ответ, на который вы ссылались, касался конкретного сценария, где им необходимо было обернуть элементы, у которых были разные элементы до и после них. У вас есть такое требование, или это так же просто, как ваш пример? – JLRishe

+0

Все элементы dosage.sec должны быть смежными внутри исходного документа (между ними нет других элементов), поэтому оно проще. Я изменил свой пример, поскольку понял, что я не точно изобразил, что у меня есть другие элементы в монографии до и после блока dosage.sec – HorusKol

ответ

0

У меня было еще несколько проблем на пути - во-первых, я обнаружил, что элементы dosage.sec не были в непрерывном блоке, и я ошибочно создавал два контейнера для дозировки.

Эти шаблоны решить мои проблемы:

<!-- wrap dosage.sec elements in a dosage container --> 
<xsl:template match="monograph/dosage.sec" name="dosage.sec"> 
    <xsl:param name="drugname" /> 

    <xsl:copy> 
     <xsl:apply-templates> 
      <xsl:with-param name="drugname" select="$drugname" /> 
     </xsl:apply-templates> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="monograph/dosage.sec[not(preceding::dosage.sec)]"> 
    <xsl:param name="drugname" /> 

    <dosage> 
     <xsl:call-template name="dosage.sec"> 
      <xsl:with-param name="drugname" select="$drugname" /> 
     </xsl:call-template> 

     <xsl:apply-templates mode="copy" select="following::dosage.sec"> 
      <xsl:with-param name="drugname" select="$drugname" /> 
     </xsl:apply-templates> 
    </dosage> 
</xsl:template> 

<xsl:template match="monograph/dosage.sec" mode="copy"> 
    <xsl:param name="drugname" /> 

    <xsl:call-template name="dosage.sec"> 
     <xsl:with-param name="drugname" select="$drugname" /> 
    </xsl:call-template> 
</xsl:template> 

<xsl:template match="monograph/dosage.sec[(preceding::dosage.sec)]" /> 
2

Как об этом:

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

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

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

    <!-- rename children dosage.sec --> 
    <xsl:template match="dosage.sec/dosage.sec"> 
    <dosage.qual> 
     <xsl:apply-templates /> 
    </dosage.qual> 
    </xsl:template> 
</xsl:stylesheet> 

Когда на выходе образца, это производит:

<monograph> 
    <dosage> 
    <dosage.sec> 
     <dosage.qual>asgfd</dosage.qual> 
     <dosage.qual>asgfd</dosage.qual> 
    </dosage.sec> 
    <dosage.sec> 
     <dosage.qual>asgfd</dosage.qual> 
     <dosage.qual>asgfd</dosage.qual> 
    </dosage.sec> 
    <dosage.sec> 
     <dosage.qual>asgfd</dosage.qual> 
     <dosage.qual>asgfd</dosage.qual> 
    </dosage.sec> 
    </dosage> 
</monograph>