2012-05-02 5 views
2

Я видел вопросы, связанные с Ruby и т. Д. Я не видел никаких ответов, которые охватывали бы этот случай.Удалить несогласованные круглые скобки и несогласованные скобки из XML-контента

Я использую XSLT для преобразования XML-документа. Я вынужден использовать XSLT 1.0, поскольку приложение, использующее XSLT и XPATH, все еще находится на 1.0.

Вы использовали бы функцию Javascript, встроенную в XSL, с помощью регулярного выражения?

У меня есть XML-код, как это:

<document> 
<content name="PROD_MAJ_CLS_CD" type="text" vse-streams="2" u="20" action="cluster" weight="1">2</content> 
<content name="PART_DESC_SHORT" type="text" vse-streams="2" u="22" action="cluster" weight="1">SCREW-ROCKER</content> 
</document> 

Атрибут содержание, где имя = "PART_DESC_SHORT" может иметь круглые скобки и скобки в нем

Спасибо, Пол

+0

Да, но убедитесь, чтобы скрыть HTML элемента по умолчанию, чтобы не видеть оригинальный текст перед выполняет JavaScript. –

+0

Можете ли вы привести примеры входов с непревзойденными парами/скобками и ожидаемыми выходами? Вам нужно обрабатывать сложные случаи, такие как 'A [B {c] d} E]' (какую правую квадратную скобку следует удалить?) –

+0

Вот несколько примеров: AXLE GP (SID SEAL (TRUMPE AXLE AS. (W/ ARM AS-PUSH ( KIT-COIL (MT –

ответ

0

В вашем примере, нет круглых скобок, и все являются открытыми круглыми скобками; для этого случая задача удаления не имеет себе равных скобки и скобки составляет для удаления все скобки и скобки. Это легко делается с помощью функции translate:

<xsl:value-of select="translate(.,'([','')"/> 

Если вам действительно нужно сохранить согласованные скобки и перевести ввод формы a(b[c]d(e в ab[c]de, то самый простой способ сделать это в XSLT является с рекурсивным именем шаблона который принимает два параметра: входную строку и стек, записывающие материал, обработанный до сих пор. (Стек может быть просто последовательностью строк, разделенных выбранным разделителем, который, как вы надеетесь, не будет отображаться на входе. Поскольку вы показываете ввод как исходящий от значения атрибута, &amp;#x9;, вероятно, будет безопасным выбором (он будет были нормализованы из ввода, если производитель данных не использовал для него числовую ссылку на символ), но вы можете использовать |||never-use-this-string-in-a-part-description||| вместо этого, если хотите.)

При первоначальном вызове вы передаете только входную строку, и пусть стека по умолчанию пустым.

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

  • для «(» и «[», нажмите новую строку в стек.
  • для «]» и «)», соответствующий первому символу верхнего элемента в стеке, дважды вытащите стек, объедините элемент 2, элемент 1 (старый верхний элемент) и символ «] "или") ", и нажмите конкатенацию на стек.
  • Для «]» и «), которые не совпадают, вход плохо сбалансирован, и вам нужно что-то сделать. (В коде здесь выпадает символ.)
  • Для любого другого символа добавьте его к верхнему элементу в стеке.

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

Когда строка ввода исчерпана, и в стеке имеется более одного элемента, верхняя часть верхней части стека должна быть удалена, а верхний элемент (минус скобка) добавлен к следующему элементу.

Как только стек упадет до одного элемента, этот элемент содержит нужную вам строку.

Здесь в XSLT:

<xsl:template name="paren-match-or-strip"> 
    <xsl:param name="input"/> 
    <xsl:param name="stack"/> 

    <xsl:variable name="char" 
       select="substring($input,1,1)"/> 
    <xsl:variable name="stacktop" 
       select="substring-before($stack,$sep)"/> 
    <xsl:variable name="stackrest" 
       select="substring-after($stack,$sep)"/> 

    <xsl:choose> 
    <xsl:when test="not($input = '')"> 
     <xsl:choose> 
     <xsl:when test="$char = '(' or $char = '['"> 
      <!--* Push another potential-left-brace on the stack *--> 
      <xsl:call-template name="paren-match-or-strip"> 
      <xsl:with-param name="input" 
          select="substring($input,2)"/> 
      <xsl:with-param name="stack" 
         select="concat(
           $char, 
           $sep, 
           $stack 
           )"/> 
      </xsl:call-template> 
     </xsl:when> 
     <xsl:when test="($char = ']' and substring($stacktop,1,1) = '[') 
         or 
         ($char = ')' and substring($stacktop,1,1) = '(') 
         "> 
      <!--* Match the left brace at the top of the stack *--> 
      <xsl:variable name="stacktop2" 
         select="substring-before($stackrest,$sep)"/> 
      <xsl:variable name="stackrest2" 
         select="substring-after($stackrest,$sep)"/> 

      <xsl:call-template name="paren-match-or-strip"> 
      <xsl:with-param name="input" 
          select="substring($input,2)"/> 
      <xsl:with-param name="stack" 
         select="concat(
           $stacktop2, 
           $stacktop, 
           $char, 
           $sep, 
           $stackrest 
           )"/> 
      </xsl:call-template> 
     </xsl:when> 
     <xsl:when test="$char = ']' or $char = ')'"> 
      <!--* Unmatched right brace, drop it silently *-->  
      <xsl:call-template name="paren-match-or-strip"> 
      <xsl:with-param name="input" 
          select="substring($input,2)"/> 
      <xsl:with-param name="stack" 
         select="$stack"/> 
      </xsl:call-template> 
     </xsl:when>  
     <xsl:otherwise> 
      <xsl:call-template name="paren-match-or-strip"> 
      <xsl:with-param name="input" 
          select="substring($input,2)"/> 
      <xsl:with-param name="stack" 
          select="concat(
            $stacktop, 
            $char, 
            $sep, 
            $stackrest 
            )"/> 
      </xsl:call-template> 
     </xsl:otherwise> 
     </xsl:choose> 
    </xsl:when> 
    <xsl:when test="$input = '' and contains($stackrest,$sep)"> 
     <!--* Input is exhausted and at least one unmatched 
      * parenthesis is on the stack. 
      *--> 
     <xsl:variable name="stacktop2" 
        select="substring-before($stackrest,$sep)"/> 
     <xsl:variable name="stackrest2" 
        select="substring-after($stackrest,$sep)"/> 

     <xsl:call-template name="paren-match-or-strip"> 
     <xsl:with-param name="input" 
         select="$input"/> 
     <xsl:with-param name="stack" 
         select="concat(
           $stacktop2, 
           substring($stacktop,2), 
           $sep, 
           $stackrest2 
           )"/> 
     </xsl:call-template> 

    </xsl:when> 
    <xsl:otherwise> 
     <!--* input is exhausted, stack only has one item *--> 
     <xsl:value-of select="substring-before($stack,$sep)"/> 
    </xsl:otherwise> 
    </xsl:choose> 

</xsl:template> 
Смежные вопросы