2014-01-09 4 views
0

Обновлено включить некоторые дополнительные нюансысложный сценарий для XSLT

У меня есть сценарий XML, который потребует некоторых сложных XSLT. Я пытался понять это самостоятельно, но пока не увенчался успехом.

Начнем с того, что здесь представлена ​​составная структура XML.

<Author id="1234"> 
    <reviews>poor</reviews> 
    <Media>  
    <MediaSet> 
     <MediaCode type="CD">474747</MediaCode> 
    </MediaSet> 
    <MediaSet> 
     <MediaCode type="CD">535353</MediaCode> 
    </MediaSet> 
    <MediaSet> 
     <MediaCode type="eBook">989898</MediaCode> 
    </MediaSet> 
    <MediaSet> 
     <MediaCode type="download">202020</MediaCode> 
    </MediaSet> 
    <MediaSet> 
     <MediaCode type="book">161616</MediaCode> 
    </MediaSet> 
    <MediaSet> 
     <MediaCode type="DVD">828282</MediaCode> 
    </MediaSet> 
    <MediaSet> 
     <OtherCode type="widget" number="747474"/> <!--note different element name and structure--> 
    </MediaSet> 
    </Media> 
    <name>JimBob</name> 
</Author> 

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

<row> 
    <field name="authorID">1234</field> 
    <field name="reviews">poor</field> 
    <field name="CD">474747</field> 
    <field name="name">JimBob</field> 
</row> 
<row> 
    <field name="authorID">1234</field> 
    <field name="reviews">poor</field> 
    <field name="CD">535353</field> 
    <field name="name">JimBob</field> 
</row> 
<row> 
    <field name="authorID">1234</field> 
    <field name="reviews">poor</field> 
    <field name="eBook">989898</field> 
    <field name="name">JimBob</field> 
</row> 
<row> 
    <field name="authorID">1234</field> 
    <field name="reviews">poor</field> 
    <field name="download">989898</field> 
    <field name="name">JimBob</field> 
</row> 
<row> 
    <field name="authorID">1234</field> 
    <field name="reviews">poor</field> 
    <field name="widget">555555</field> 
    <field name="name">JimBob</field> 
</row> 
  • CD, электронные книги , загрузка может происходить в ноль или более раз.
  • Мне нужно создать отдельную строку для каждого экземпляра
  • Есть определенные элементы (например, «книга», «DVD» и многие другие), которые я хочу игнорировать.
  • Есть 100 000 «авторов» со своей уникальной комбинацией «MediaCodes».
  • Есть смешанные элементы, которые мне нужны для извлечения данных из

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

Это что-то, что можно управлять только с помощью XSLT или мне придется использовать другой язык для обработки?

Обратите внимание: файл XML, который я обрабатываю, имеет гораздо более сложную структуру, а - это примерно 325MB.

+1

Если у вас уже есть код, который можно взять из исходной структуры XML в XML-структуру строки/поля, отправьте его здесь (фрагмент, если он слишком длинный в полном объеме). –

+0

Я ответил на ваш вопрос «как есть». Тем не менее, IMHO вы делаете ошибку, сглаживая структуру, прежде чем импортировать ее в базу данных.Предполагая реляционную базу данных, вам было бы намного лучше импортировать данные дважды, в две отдельные таблицы: Authors and Media, вместо плоской таблицы с множеством избыточных повторений одних и тех же данных. –

+0

Кроме того, у вас должно быть одно поле для типа носителя: «CD», «Ebook» и т. Д. Являются * значениями * и еще одним полем для мультимедийного кода, общим для всех типов. В противном случае поиск базы данных станет очень громоздким. –

ответ

2

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

<MediaCode type="eBook">989898</Type> 

Предполагая, что скорректированный ввод, который также включает в себя корневой элемент:

<Authors> 
    <Author id="1234"> 
     <reviews>poor</reviews> 
     <MediaSet> 
      <MediaCode type="CD">101</MediaCode> 
      <MediaCode type="CD">102</MediaCode> 
      <MediaCode type="eBook">111</MediaCode> 
      <MediaCode type="download">121</MediaCode> 
      <MediaCode type="book">131</MediaCode> 
     </MediaSet> 
     <name>Adam</name> 
    </Author> 
    <Author id="5678"> 
     <reviews>good</reviews> 
     <MediaSet> 
      <MediaCode type="CD">201</MediaCode> 
      <MediaCode type="eBook">202</MediaCode> 
      <MediaCode type="download">203</MediaCode> 
      <MediaCode type="book">204</MediaCode> 
     </MediaSet> 
     <name>Betty</name> 
    </Author> 
</Authors> 

можно использовать таблицу стилей, как это:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/> 

<xsl:template match="/"> 
<rows> 
    <xsl:for-each select="Authors/Author/MediaSet/MediaCode[@type!='book']"> 
     <row> 
      <field name="authorID"><xsl:value-of select="../../@id" /></field> 
      <field name="reviews"><xsl:value-of select="../../reviews" /></field> 
      <field name="{@type}"><xsl:value-of select="." /></field> 
      <field name="name"><xsl:value-of select="../../name" /></field> 
     </row> 
    </xsl:for-each> 
</rows> 
</xsl:template> 
</xsl:stylesheet> 

произвести следующий результат (опять же, с корневой элемент):

<?xml version="1.0" encoding="utf-8"?> 
<rows> 
    <row> 
    <field name="authorID">1234</field> 
    <field name="reviews">poor</field> 
    <field name="CD">101</field> 
    <field name="name">Adam</field> 
    </row> 
    <row> 
    <field name="authorID">1234</field> 
    <field name="reviews">poor</field> 
    <field name="CD">102</field> 
    <field name="name">Adam</field> 
    </row> 
    <row> 
    <field name="authorID">1234</field> 
    <field name="reviews">poor</field> 
    <field name="eBook">111</field> 
    <field name="name">Adam</field> 
    </row> 
    <row> 
    <field name="authorID">1234</field> 
    <field name="reviews">poor</field> 
    <field name="download">121</field> 
    <field name="name">Adam</field> 
    </row> 
    <row> 
    <field name="authorID">5678</field> 
    <field name="reviews">good</field> 
    <field name="CD">201</field> 
    <field name="name">Betty</field> 
    </row> 
    <row> 
    <field name="authorID">5678</field> 
    <field name="reviews">good</field> 
    <field name="eBook">202</field> 
    <field name="name">Betty</field> 
    </row> 
    <row> 
    <field name="authorID">5678</field> 
    <field name="reviews">good</field> 
    <field name="download">203</field> 
    <field name="name">Betty</field> 
    </row> 
</rows> 
+0

Благодарим вас за комментарии, я изменил вопрос, чтобы отразить дополнительную сложность, не представленную в моем первоначальном примере. – user859501

+1

@ user859501 Это довольно тривиальное изменение: просто используйте * вместо MediaCode в пути 'for-each'. Я также повторяю свою рекомендацию не делать этого вообще. –

1

AFAIKS, это не сложно вообще:

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

    <xsl:output indent="yes"/> 

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

    <xsl:template match="text()"/> 

    <xsl:template match="Author/MediaSet/MediaCode[@type!='book']"> 
    <row> 
     <field name="authorId"><xsl:value-of select="../../@id"/></field> 
     <field name="reviews"><xsl:value-of select="../../reviews"/></field> 
     <field name="{@type}"><xsl:value-of select="."/></field> 
     <field name="name"><xsl:value-of select="../../name"/></field> 
    </row> 
    </xsl:template> 
</xsl:stylesheet> 
+0

Благодарим вас за комментарии, я изменил квест, чтобы отразить дополнительную сложность, не представленную в моем первоначальном примере. – user859501

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