Oracle XSLT: пространство имен по умолчанию приводит к пустым тегам - PullRequest
1 голос
/ 20 сентября 2010

Я думаю, что лучший способ задать этот вопрос: как мне указать пространство имен по умолчанию для корневого элемента в выводе? Делаем это:

<xsl:template match="/">
        <r xmlns:s"http://www.mycompany.com/s/schema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.mycompany.com/default/schema" >
....
....

Дает мне ошибку в Oracle:

ORA-31011: XML Parsing Failed
ORA-19201: Error occurred in in XML Processing
LPX-00604: Invalid attribute 'nIfNotExist', for attribute 'name'
ORA-06512: at SYS.XMLType at line 74 
ORA-06512: at line 24

, где 'nIfNotExist' - это шаблон:

 <xsl:template name="nIfNotExist" xmlns:scom="http://www.mycomapny.com/s/schema">
  <xsl:param name="nodeToTest"/>
  <xsl:param name="nodeName"/>
                ...

Я хочу, чтобы в полученном документе корневой элемент выглядел так:

<r xmlns:s="http://www.mycompany.com/s/schema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.mycompany.com/default/schema">

Я хочу "http://www.mycompany.com/default/schema" в качестве пространства имен по умолчанию, чтобы документ мог пройти проверку XSD. В противном случае я должен добавить его вручную перед запуском проверки (не вариант для пакетной обработки).

EDIT

Я пробовал это:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:s="http://www.mycompany.com/schema"
 xmlns="http://www.mycompany.com/def_schema">

В результате получается документ без данных, например:

<r xmlns:s="http://www.mycompany.com/schema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.mycompany.com/def_schema">
    <a></a>
    <s:b></s:b>
    <c></c>
    ....

Это должно было быть:

<r xmlns:s="http://www.mycompany.com/schema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.mycompany.com/def_schema">
    <a>123</a>
    <s:b>ABC34L</s:b>
    <c>7.092381</c>

UPDATE

Исходные данные выглядят примерно так (входные данные, которые я получаю, не имеют определенных пространств имен):

<ROOT_NODE>
    <DATA_A>1234</DATA_A>
    <DATA_B>34567</DATA_B>
    <OTHER_DATA_C>7.123456</OTHER_DATA_C>
</ROOT_NODE>

Желаемый вывод

<r xmlns:s="http://www.mycompany.com/schema"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
   xmlns="http://www.mycompany.com/def_schema">
    <a>1234</a>
    <s:b>34567</s:b>
    <c>7.123456</c>
</r>

Ответы [ 3 ]

1 голос
/ 21 сентября 2010

Это преобразование :

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:s="http://www.mycompany.com/schema"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns="http://www.mycompany.com/def_schema"
 >
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:template match="/*">
  <r>
   <xsl:apply-templates/>
  </r>
 </xsl:template>

 <xsl:template match="DATA_A">
  <a>
   <xsl:apply-templates/>
  </a>
 </xsl:template>

  <xsl:template match="OTHER_DATA_C">
   <c>
    <xsl:apply-templates/>
   </c>
  </xsl:template>

  <xsl:template match="DATA_B">
   <s:b>
    <xsl:apply-templates/>
   </s:b>
  </xsl:template>
</xsl:stylesheet>

при применении к предоставленному документу XML :

<ROOT_NODE>
    <DATA_A>1234</DATA_A>
    <DATA_B>34567</DATA_B>
    <OTHER_DATA_C>7.123456</OTHER_DATA_C>
</ROOT_NODE>

дает желаемый результат :

<r xmlns:s="http://www.mycompany.com/schema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.mycompany.com/def_schema">
    <a>1234</a>
    <s:b>34567</s:b>
    <c>7.123456</c>
</r>
0 голосов
/ 30 сентября 2010

Существует много возможных решений, но ни одно из них не работает в Oracle, от PL / SQL. Один из других разработчиков здесь «решил» это, преобразовав объект XML в CLOB, выполнив некоторые манипуляции со строками для принудительного использования пространства имен по умолчанию в корневом элементе, а затем преобразовав обратно в XML для следующего шага ... нравится, но работает ...

0 голосов
/ 20 сентября 2010

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

Я думаю, что вы, вероятно, упускаете из виду то, что объявления пространства имен в XSLT-преобразовании также применяются к шаблонам XPath в преобразовании.Держу пари, что тесты узлов XPath в вашем преобразовании не соответствуют ни одному из входных узлов, потому что входные узлы находятся в пустом пространстве имен, а не в пространстве имен, которое вы объявили в преобразовании.

Что вывероятно, нужно сделать что-то вроде этого:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"  
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
 xmlns:s="http://www.mycompany.com/schema" 
 xnlns:no=""
 xmlns="http://www.mycompany.com/def_schema">

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

<xsl:template match="no:foo">
   <foo>...</foo>
</xsl:template>

Это, кстати, один изПричины существования xsl:element - вы можете создать шаблон, который преобразует элементы из одного пространства имен в другое, например:

<xsl:template match="no:*">
   <xsl:element name="{local-name()}">
      <xsl:apply-templates select="node()|@*"/>
   </xsl:element>
</xsl:element>

Редактировать:

У меня естьДо этого не играл с пространством имен таким образом, и оказалось, что вышеупомянутое на самом деле не является законным.Вы не можете указать пространство имен с префиксом пространства имен.Таким образом, вы не можете использовать целевое пространство имен в качестве пространства имен по умолчанию для вашего преобразования, потому что тогда у вас нет возможности указать XPath найти элементы в исходном документе.

Вы можете указать выходное пространство имен с помощьюпрефикс, например:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"  
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
 xmlns:s="http://www.mycompany.com/schema" 
 xmlns:out="http://www.mycompany.com/def_schema">

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

<xsl:template match="foo">
   <xsl:element name="foo" namespace="http://www.mycompany.com/def_schema">
      ...
   </xsl:element>
</xsl:template>
...