2015-07-28 6 views
1

У меня есть файл XML, который выглядит, как это (упрощенный):Использования Schematron быстрого исправления помечать отдельные слова в смешанных содержательных элементах

<defs> 
    <def>Pure text</def> 
    <def>Mixed content, cuz there is also another: <element>element inside</element> and more.</def> 
    <def><element>Text nodes within elements other than def are ok.</element></def> 
<defs> 

Я пытаюсь написать правило Shematron с быстрыми решениями, которые позволили бы мне принимать каждое отдельное слово в defs со смешанным контентом и обертывать их каждый в элементах <w>, а также обертывать знаки пунктуации в <pc> элементах. Другими словами, после применения быстрых решений я хотел бы получить

<defs> 
    <def>Pure text.</def> 
    <def><w>Mixed</w> <w>content</w><pc>,</pc> <w>cuz</w> <w>there</w> <w>is</w> <w>also</w> <w>another</w><pc>:</pc> <element>element inside</element> <w>and</w> <w>more</w><pc>.</pc></def> 
    <def><element>Text nodes within elements other than def are ok.</element></def> 
<defs> 

Промежутки между <w> с и <pc> с все в порядке.

Теперь определение смешанного контента легко - я думаю, что получаю это правильно. Проблема в том, что я не знаю, как токенизировать строки в Schematron, а затем применять исправление для каждого токена. Вот как далеко я получил:

<sch:pattern id="mixed"> 
    <sch:rule context="def[child::text()][child::*]"> 
     <sch:report test="tokenize(child::text(), '\s+')" sqf:fix="mix_in_def"> 
      Element has mixed content 
      <!-- the above this gives me the error: a sequence of more than one item is not allowed as the first argument of tokenize--> 
     </sch:report> 
     <sqf:fix id="mix_in_def"> 
      <sqf:description> 
       <sqf:title>Wrap words in w</sqf:title> 
       <sqf:p>Fixes the mixed content in def by treating each non-tagged string as w.</sqf:p> 
      </sqf:description> 
      <sqf:replace match="." node-type="element" target="w"> 
       <!--how do i represent the content of the matched token?--> 
      </sqf:replace> 
      <!-- also do i create an altogether separate rule for punctuation?--> 
     </sqf:fix> 
    </sch:rule> 
</sch:pattern> 

Любые советы были бы весьма признательны.

линь

+0

Помог ли мой ответ? – sergioFC

+0

Я все еще жду некоторых отзывов, пожалуйста, скажите, был ли мой ответ полезен или нет. – sergioFC

+0

совершенно. Мне очень жаль, что я не смог подтвердить ваш ответ. моя вина. – Tench

ответ

2

Вы можете использовать XSL, посмотрите на этом примере (это объясняется в комментариях к коду):

<sch:pattern id="mixed"> 
    <!-- Your context is now def => this makes easier add new def reports --> 
    <sch:rule context="def"> 

     <!-- So now you report every def that has text and elements --> 
     <sch:report test="child::text() and child::*" sqf:fix="mix_in_def"> 
      Element has mixed content 
      <!-- What you were doing before where causing error because you were passing a sequence of text nodes to tokenize (it expects a string) --> 
     </sch:report> 

     <sqf:fix id="mix_in_def"> 
      <sqf:description> 
       <sqf:title>Wrap words in w</sqf:title> 
       <sqf:p>Fixes the mixed content in def by treating each non-tagged string as w.</sqf:p> 
      </sqf:description> 

      <!-- Replace every mixed text node of this def (this is called for every matched node) --> 
      <sqf:replace match="child::text()"> 
        <!-- Tokenize this text node => for each token choose... --> 
        <xsl:for-each select="tokenize(., '\s+')"> 
         <!-- For this token choose --> 
         <xsl:choose> 
          <!-- If text is one of this (,.:) Please note that you are using \s+ to separate tokens. So a comma is only a token if it is separated by spaces --> 
          <xsl:when test=". = (',', '.', ':', 'is')"> <!-- "is" just to test results --> 
           <pc><xsl:value-of select="."/></pc> 
          </xsl:when> 
          <!-- Otherwise wrap it in <w> --> 
          <xsl:otherwise> 
           <w><xsl:value-of select="."/></w> 
          </xsl:otherwise> 
         </xsl:choose> 
        </xsl:for-each> 
      </sqf:replace> 

     </sqf:fix> 
    </sch:rule> 
</sch:pattern> 

Вы должны будете адаптировать это к вашим конкретным проблемам, но я думаю, что это помочь тебе.

+0

Интересное предложение, @sergioFC! Вы случайно не знаете, где можно найти больше информации о смешивании XSLT с правилами Schematron? Я мог бы найти наиболее конкретные указатели в разделе «Язык запросов для XSLT 2» в [Документация Schematron ISO] (http://standards.iso.org/ittf/PubliclyAvailableStandards/c055982_ISO_IEC_19757-3_2016.zip). Там '', '' и '' упоминаются как разрешенные материалы до '' элементов, но до сих пор я ничего не нашел в XSLT-инструкциях _inside_ patterns. Он работает, однако, поэтому он должен быть разрешен. – rvdb

+0

Спасибо. Боюсь, я не могу предоставить док. Как я вижу, спецификации Schematron говорят, что вы можете определить свою собственную функцию 'xsl: function', чтобы повторно использовать их последние. См. Эту функцию [xsl: внутри примера Schematron] (http://pastebin.com/Ue5mgRCy). Код XSLT в моем ответе на этот пост является частью спецификации Schematron QuickFix, он НЕ является частью самой спецификации Schematron. [Schematron QuickFix] (http://www.schematron-quickfix.com/quickFix/guide.html) был создан спустя годы после Schematron, чтобы позволить исправлениям XML проблемы, которые Schematron может сообщить, но это расширение Schematron, а не его часть – sergioFC

+1

Хорошо, спасибо за разъяснение контекста SQF. Тем не менее, я попытался обрезать его (см. [Примеры файлов в этом контексте] (https://gist.github.com/rvdb/ad2dc77bf5fc33b4e02cb3e415d19888)), и он, похоже, тоже работает в Schematron ns: все виды инструкций XSLT просто исполняются в шаблонах Schematron. Для моих целей это просто замечательно, но я хотел бы знать, взволнована ли я особенностью или ошибкой (как спецификацией, так и реализацией). Я просто хотел указать на это, но попытаюсь найти более подходящий форум, чтобы попытаться его воплотить. – rvdb