Выберите и измените узел, оставив остальное без изменений с помощью xlst - PullRequest
0 голосов
/ 21 мая 2018

У меня есть следующий XML:

<?xml version="1.0" encoding="utf-8" ?>
<DOCUMENT>
    <SECTION>
        <PARAGRAPH TRACK="4">
            <SENTENCE NAME="PRIMARY" COUNT="4">
                <TOKEN BEGIN="9" END="11" SENTENCE_BEGIN="0" SENTENCE_END="156" />
                <TOKEN BEGIN="32" END="37" SENTENCE_BEGIN="0" SENTENCE_END="156" />
                <TOKEN BEGIN="167" END="169" SENTENCE_BEGIN="158" SENTENCE_END="316" />
                <TOKEN BEGIN="210" END="215" SENTENCE_BEGIN="158" SENTENCE_END="316" />
            </SENTENCE>
            <SENTENCE NAME="SECONDARY" COUNT="2">
                <TOKEN BEGIN="139" END="141" SENTENCE_BEGIN="0" SENTENCE_END="156" PROP="A" DOUBLE="YES" />
                <TOKEN BEGIN="143" END="145" SENTENCE_BEGIN="0" SENTENCE_END="156" PROP="B" />
            </SENTENCE>
            <SENTENCE NAME="SECONDARY" COUNT="1">
                <TOKEN BEGIN="17" END="19" SENTENCE_BEGIN="0" SENTENCE_END="156" PROP="C" DOUBLE="YES" />                    
            </SENTENCE>
        </PARAGRAPH>
    </SECTION>
</DOCUMENT>

И мне нужно получить следующий результат с узлом TOKEN, выбранным оператором IF, обновленным атрибутом NEW:

<?xml version="1.0" encoding="utf-8" ?>
<DOCUMENT>
    <SECTION>
        <PARAGRAPH TRACK="4">
            <SENTENCE NAME="PRIMARY" COUNT="4">
                <TOKEN BEGIN="9" END="11" SENTENCE_BEGIN="0" SENTENCE_END="156" />
                <TOKEN BEGIN="32" END="37" SENTENCE_BEGIN="0" SENTENCE_END="156" />
                <TOKEN BEGIN="167" END="169" SENTENCE_BEGIN="158" SENTENCE_END="316" />
                <TOKEN BEGIN="210" END="215" SENTENCE_BEGIN="158" SENTENCE_END="316" />
            </SENTENCE>
            <SENTENCE NAME="SECONDARY" COUNT="2">
                <TOKEN BEGIN="139" END="141" SENTENCE_BEGIN="0" SENTENCE_END="156" PROP="A" DOUBLE="YES" />
                <TOKEN BEGIN="143" END="145" SENTENCE_BEGIN="0" SENTENCE_END="156" PROP="B" />
            </SENTENCE>
            <SENTENCE NAME="SECONDARY" COUNT="1">
                <TOKEN BEGIN="17" END="19" SENTENCE_BEGIN="0" SENTENCE_END="156" PROP="C" DOUBLE="YES" NEW="YES" />
                <TOKEN></TOKEN>
            </SENTENCE>
        </PARAGRAPH>
    </SECTION>
</DOCUMENT>

Используя следующее преобразование XSLT, я получаю неверный результат, когда узел TOKEN, выбранный оператором IF, копируется в начало дерева:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output indent="yes"/>
  <xsl:strip-space elements="*"/>
 <xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
 </xsl:template>
  <xsl:key name="primary_tokens" 
    match="SENTENCE[@NAME='PRIMARY']/TOKEN" 
    use="concat(@SENTENCE_BEGIN,'|',@SENTENCE_END)"/>
  <xsl:template match="/*">
    <xsl:for-each select=".//TOKEN[@DOUBLE='YES'][key('primary_tokens',concat(@SENTENCE_BEGIN,'|',@SENTENCE_END))]">
      <xsl:if test="key('primary_tokens',concat(@SENTENCE_BEGIN,'|',@SENTENCE_END))[@BEGIN > current()/@BEGIN]">
        <xsl:copy>
            <xsl:attribute name="NEW">YES</xsl:attribute>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy> 
      </xsl:if>
    </xsl:for-each>
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

Нежелательный результат:

<?xml version="1.0" encoding="utf-16"?>
<TOKEN NEW="YES" BEGIN="17" END="19" SENTENCE_BEGIN="0" SENTENCE_END="156" PROP="C" DOUBLE="YES" />
<DOCUMENT>
  <SECTION>
    <PARAGRAPH TRACK="4">
      <SENTENCE NAME="PRIMARY" COUNT="4">
        <TOKEN BEGIN="9" END="11" SENTENCE_BEGIN="0" SENTENCE_END="156" />
        <TOKEN BEGIN="32" END="37" SENTENCE_BEGIN="0" SENTENCE_END="156" />
        <TOKEN BEGIN="167" END="169" SENTENCE_BEGIN="158" SENTENCE_END="316" />
        <TOKEN BEGIN="210" END="215" SENTENCE_BEGIN="158" SENTENCE_END="316" />
      </SENTENCE>
      <SENTENCE NAME="SECONDARY" COUNT="2">
        <TOKEN BEGIN="139" END="141" SENTENCE_BEGIN="0" SENTENCE_END="156" PROP="A" DOUBLE="YES" />
        <TOKEN BEGIN="143" END="145" SENTENCE_BEGIN="0" SENTENCE_END="156" PROP="B" />
      </SENTENCE>
      <SENTENCE NAME="SECONDARY" COUNT="1">
        <TOKEN BEGIN="17" END="19" SENTENCE_BEGIN="0" SENTENCE_END="156" PROP="C" DOUBLE="YES" />
      </SENTENCE>
    </PARAGRAPH>
  </SECTION>
</DOCUMENT>

Я предложил возможное решение, добавив в xsl:template условие match="//SECTION/PARAGRAPH/SENTENCE[@NAME='SECONDARY']/TOKEN.К сожалению, даже это решение не является правильным, поскольку узел содержимого TOKEN просто копируется в узел SENTENCE:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output indent="yes"/>
  <xsl:strip-space elements="*"/>
 <xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
 </xsl:template>
  <xsl:key name="primary_tokens" 
    match="SENTENCE[@NAME='PRIMARY']/TOKEN" 
    use="concat(@SENTENCE_BEGIN,'|',@SENTENCE_END)"/>
  <xsl:template match="//SECTION/PARAGRAPH/SENTENCE[@NAME='SECONDARY']/TOKEN">
    <xsl:for-each select="current()[key('primary_tokens',concat(@SENTENCE_BEGIN,'|',@SENTENCE_END))]">
      <xsl:if test="key('primary_tokens',concat(@SENTENCE_BEGIN,'|',@SENTENCE_END))[@BEGIN > current()/@BEGIN]">


            <xsl:attribute name="NEW">YES</xsl:attribute>
            <xsl:apply-templates select="@*|node()"/>


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

Неправильный вывод с TOKEN в узле SENTENCE:

<?xml version="1.0" encoding="utf-16"?>
<DOCUMENT>
  <SECTION>
    <PARAGRAPH TRACK="4">
      <SENTENCE NAME="PRIMARY" COUNT="4">
        <TOKEN BEGIN="9" END="11" SENTENCE_BEGIN="0" SENTENCE_END="156" />
        <TOKEN BEGIN="32" END="37" SENTENCE_BEGIN="0" SENTENCE_END="156" />
        <TOKEN BEGIN="167" END="169" SENTENCE_BEGIN="158" SENTENCE_END="316" />
        <TOKEN BEGIN="210" END="215" SENTENCE_BEGIN="158" SENTENCE_END="316" />
      </SENTENCE>
      <SENTENCE NAME="SECONDARY" COUNT="2">
        <TOKEN BEGIN="139" END="141" SENTENCE_BEGIN="0" SENTENCE_END="156" PROP="A" DOUBLE="YES" />
        <TOKEN BEGIN="143" END="145" SENTENCE_BEGIN="0" SENTENCE_END="156" PROP="B" />
      </SENTENCE>
      <SENTENCE NAME="SECONDARY" COUNT="1" NEW="YES" BEGIN="17" END="19" SENTENCE_BEGIN="0" SENTENCE_END="156" PROP="C" DOUBLE="YES">
        <TOKEN BEGIN="17" END="19" SENTENCE_BEGIN="0" SENTENCE_END="156" PROP="C" DOUBLE="YES" />
        <TOKEN />
      </SENTENCE>
    </PARAGRAPH>
  </SECTION>
</DOCUMENT>

Мой вопрос: как получить желаемый результат, о котором говорилось выше?Моя вторая попытка близка к хорошему решению?

1 Ответ

0 голосов
/ 21 мая 2018

Я думаю, что ваша вторая попытка близка;Вы хотите соответствовать TOKEN, если хотите обновить.

Попробуйте это ...

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

  <xsl:key name="primary_tokens" 
    match="SENTENCE[@NAME='PRIMARY']/TOKEN" 
    use="concat(@SENTENCE_BEGIN,'|',@SENTENCE_END)"/>

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

  <xsl:template match="TOKEN[@DOUBLE='YES']">
    <xsl:copy>
      <xsl:if test="key('primary_tokens',concat(@SENTENCE_BEGIN,'|',@SENTENCE_END))[@BEGIN > current()/@BEGIN]">
        <xsl:attribute name="NEW">YES</xsl:attribute>
      </xsl:if>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

Fiddle: http://xsltfiddle.liberty -development.net / bdxtpX

...