2013-05-14 2 views
1

У нас есть инструмент, который создает нежелательный элемент XML, и мы используем XSLT для перевода его в требуемый формат.Generic XSLT transform для управления подобными данными XML

Мы пишем другой XSLT для каждого XML, сгенерированного файлом. например один для XML-клиентов, один для XML-документов заказов и т. д.

Ниже приведены несколько файлов данных XML, полученных с помощью инструмента и фактического выпуска продукции ожидается

Клиенты

Tool сгенерированных XML

<Message> 
    <Data> 
    <CustomerArray> 
     <Customer> 
     <X> 
      <Name>John</Name> 
      <Id>100</Id> 
      <Roles> 
      <Role> 
       <X>Manager</X> 
       <X>Architect</X> 
      </Role> 
      </Roles> 
     </X> 
     <X> 
      <Name>Doe</Name> 
      <Id>102</Id> 
      <Roles> 
      <Role> 
       <X>Supervisor</X> 
       <X>Admin</X> 
      </Role> 
      </Roles> 
     </X> 
     </Customer> 
    </CustomerArray> 
    </Data> 
</Message> 

Необходимые данные XML

<Message> 
    <Data> 
    <CustomerArray> 
     <Customer> 
     <Name>John</Name> 
     <Id>100</Id> 
     <Roles> 
      <Role>Manager</Role> 
      <Role>Architect</Role> 
     </Roles> 
     </Customer> 
     <Customer> 
     <Name>Doe</Name> 
     <Id>102</Id> 
     <Roles> 
      <Role>Supervisor</Role> 
      <Role>Admin</Role> 
     </Roles> 
     </Customer> 
    </CustomerArray> 
    </Data> 
</Message> 

Заказы

Инструмент сгенерированных XML

<Message> 
    <Orders> 
    <Order> 
     <X> 
     <OrderNumber>O123</OrderNumber> 
     <CustomerID>C100</CustomerID> 
     <Quantity>100</Quantity> 
     <UnitPrice>10.0</UnitPrice> 
     </X> 
     <X> 
     <OrderNumber>O456</OrderNumber> 
     <CustomerID>C107</CustomerID> 
     <Quantity>100</Quantity> 
     <UnitPrice>5.0</UnitPrice> 
     </X> 
    </Order> 
    </Orders> 
</Message> 

Необходимые данные XML

<Message> 
    <Orders> 
    <Order> 
     <OrderNumber>O123</OrderNumber> 
     <CustomerID>C100</CustomerID> 
     <Quantity>100</Quantity> 
     <UnitPrice>10.0</UnitPrice> 
    </Order> 
    <Order> 
     <OrderNumber>O456</OrderNumber> 
     <CustomerID>C107</CustomerID> 
     <Quantity>100</Quantity> 
     <UnitPrice>5.0</UnitPrice> 
    </Order> 
    </Orders> 
</Message> 

Нежелательный элемент X может прийти на любом уровне.

Можно ли написать обобщенное преобразование XSLT для достижения этого результата во всем XML-вводе? Например, если найдено X, замените его родительским тегом и затем удалите родительский тег.

ответ

1

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

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

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

<xsl:template match="*[X]"><xsl:apply-templates/></xsl:template> 

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

Когда это преобразование применяется на следующий документ XML (первый из представленной те, с одной не- X собрата добавлены к X элементов:

<Message> 
    <Data> 
    <CustomerArray> 
     <Customer> 
     <X> 
      <Name>John</Name> 
      <Id>100</Id> 
      <Roles> 
      <Role> 
       <X>Manager</X> 
       <X>Architect</X> 
      </Role> 
      </Roles> 
     </X> 
     <somethingElse/> 
     <X> 
      <Name>Doe</Name> 
      <Id>102</Id> 
      <Roles> 
      <Role> 
       <X>Supervisor</X> 
       <X>Admin</X> 
      </Role> 
      </Roles> 
     </X> 
     </Customer> 
    </CustomerArray> 
    </Data> 
</Message> 

разыскиваемый, правильный результат производства :

<Message> 
    <Data> 
     <CustomerArray> 
     <Customer> 
      <Name>John</Name> 
      <Id>100</Id> 
      <Roles> 
       <Role>Manager</Role> 
       <Role>Architect</Role> 
      </Roles> 
     </Customer> 
     <somethingElse/> 
     <Customer> 
      <Name>Doe</Name> 
      <Id>102</Id> 
      <Roles> 
       <Role>Supervisor</Role> 
       <Role>Admin</Role> 
      </Roles> 
     </Customer> 
     </CustomerArray> 
    </Data> 
</Message> 

Обратите внимание, что решение Бородин теряет somethingElse элемент.

+0

Спасибо Димитрию! Это решило мою проблему. –

+0

@WDAY, добро пожаловать. –

2

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

Это преобразование делает то, что вы просили. Он использует переменную name, чтобы сохранить имя элемента, который является родительским, для X, чтобы избежать записи более неясного name(current()), когда дело доходит до генерации каждого выходного элемента.

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 

    <xsl:strip-space elements="*"/> 
    <xsl:output method="xml" indent="yes" encoding="UTF-8" omit-xml-declaration="yes"/> 

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

    <xsl:template match="*[X]"> 
    <xsl:variable name="name" select="name()"/> 
    <xsl:for-each select="X"> 
     <xsl:element name="{$name}"> 
     <xsl:apply-templates/> 
     </xsl:element> 
    </xsl:for-each> 
    </xsl:template> 

</xsl:stylesheet> 

выходные

Клиенты

<Message> 
    <Data> 
     <CustomerArray> 
     <Customer> 
      <Name>John</Name> 
      <Id>100</Id> 
      <Roles> 
       <Role>Manager</Role> 
       <Role>Architect</Role> 
      </Roles> 
     </Customer> 
     <Customer> 
      <Name>Doe</Name> 
      <Id>102</Id> 
      <Roles> 
       <Role>Supervisor</Role> 
       <Role>Admin</Role> 
      </Roles> 
     </Customer> 
     </CustomerArray> 
    </Data> 
</Message> 

Заказы

<Message> 
    <Orders> 
     <Order> 
     <OrderNumber>O123</OrderNumber> 
     <CustomerID>C100</CustomerID> 
     <Quantity>100</Quantity> 
     <UnitPrice>10.0</UnitPrice> 
     </Order> 
     <Order> 
     <OrderNumber>O456</OrderNumber> 
     <CustomerID>C107</CustomerID> 
     <Quantity>100</Quantity> 
     <UnitPrice>5.0</UnitPrice> 
     </Order> 
    </Orders> 
</Message> 
+0

Спасибо Бородин! –

Смежные вопросы