Переместить / скопировать узел на несколько дочерних узлов с помощью XSLT - PullRequest
0 голосов
/ 01 декабря 2010

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

У меня есть файл, который выглядит примерно так:

<Transaction>
    <Date>2010-10-14T12:06:12.164+01:00</Date>
    <Production>NO</Production>
    <Document fun:OID="1.9.101106">
        <DocumentType xmlns="">Monthly A</DocumentType>
        <RangeName xmlns="">Range Name</RangeName>
        <Name xmlns="">Equity</Name>
        <Language xmlns="">English</Language>
        <Class xmlns="">A Acc</Class>
        <Active xmlns="">YES</Active>
        <Country xmlns="">UK</Country>
        <Country xmlns="">Luxembourg</Country>
        <Country xmlns="">Denmark</Country>
        <Country xmlns="">Malta</Country>
        <Primary fun1:OID="1.9.101106" xmlns="" xmlns:fun1="DocumentXML.com">
              <Name>SISF-Indian-Equity-A-Acc-FMR-UKEN</Name>
              <FileSizeInKB>176784</FileSizeInKB>
              <FileType>pdf</FileType>
              <ReportingPeriod>September</ReportingPeriod>
              <ReportingYear>2010</ReportingYear>
        </Primary>
        <Primary fun1:OID="1.9.101118" xmlns="" xmlns:fun1="DocumentXML.com">
              <Name>SISF-Indian-Equity-A-Acc</Name>
              <FileSizeInKB>176784</FileSizeInKB>
              <FileType>pdf</FileType>
              <ReportingPeriod>September</ReportingPeriod>
              <ReportingYear>2010</ReportingYear>
        </Primary>
    </Document>
</Transaction>

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

<Transaction>
    <Date>2010-10-14T12:06:12.164+01:00</Date>
    <Production>NO</Production>
    <Document fun:OID="1.9.101106">
        <DocumentType xmlns="">Monthly A</DocumentType>
        <RangeName xmlns="">Range Name</RangeName>
        <Name xmlns="">Equity</Name>
        <Language xmlns="">English</Language>
        <Class xmlns="">A Acc</Class>
        <Active xmlns="">YES</Active>
        <Country xmlns="">UK</Country>
        <Country xmlns="">Luxembourg</Country>
        <Country xmlns="">Denmark</Country>
        <Country xmlns="">Malta</Country>
        <Primary fun1:OID="1.9.101106" xmlns="" xmlns:fun1="DocumentXML.com">
              <Name>SISF-Indian-Equity-A-Acc-FMR-UKEN</Name>
              <FileSizeInKB>176784</FileSizeInKB>
              <FileType>pdf</FileType>
              <ReportingPeriod>September</ReportingPeriod>
              <ReportingYear>2010</ReportingYear>
              <Country xmlns="">UK</Country>
              <Country xmlns="">Luxembourg</Country>
              <Country xmlns="">Denmark</Country>
              <Country xmlns="">Malta</Country>
        </Primary>
        <Primary fun1:OID="1.9.101118" xmlns="" xmlns:fun1="DocumentXML.com">
              <Name>SISF-Indian-Equity-A-Acc</Name>
              <FileSizeInKB>176784</FileSizeInKB>
              <FileType>pdf</FileType>
              <ReportingPeriod>September</ReportingPeriod>
              <ReportingYear>2010</ReportingYear>
              <Country xmlns="">UK</Country>
              <Country xmlns="">Luxembourg</Country>
              <Country xmlns="">Denmark</Country>
              <Country xmlns="">Malta</Country>
        </Primary>
    </Document>
</Transaction>

Каков наилучший подход для достижения этой цели?Нужно ли мне сначала делать копию всего документа, а затем копировать отдельные страны, или я могу как-то сделать это за один раз?

Ответы [ 3 ]

2 голосов
/ 01 декабря 2010

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

С этим (слегка измененным) входом:

<?xml version="1.0" encoding="UTF-8"?>
<Transaction xmlns:fun1="DocumentXML.com">
  <Date>2010-10-14T12:06:12.164+01:00</Date>
  <Production>NO</Production>
  <Document fun1:OID="1.9.101106">
    <DocumentType xmlns="">Monthly A</DocumentType>
    <RangeName xmlns="">Range Name</RangeName>
    <Name xmlns="">Equity</Name>
    <Language xmlns="">English</Language>
    <Class xmlns="">A Acc</Class>
    <Active xmlns="">YES</Active>
    <Country xmlns="">UK</Country>
    <Country xmlns="">Luxembourg</Country>
    <Country xmlns="">Denmark</Country>
    <Country xmlns="">Malta</Country>
    <Primary fun1:OID="1.9.101106" xmlns="" xmlns:fun1="DocumentXML.com">
      <Name>SISF-Indian-Equity-A-Acc-FMR-UKEN</Name>
      <FileSizeInKB>176784</FileSizeInKB>
      <FileType>pdf</FileType>
      <ReportingPeriod>September</ReportingPeriod>
      <ReportingYear>2010</ReportingYear>
    </Primary>
    <Primary fun1:OID="1.9.101118" xmlns="" xmlns:fun1="DocumentXML.com">
      <Name>SISF-Indian-Equity-A-Acc</Name>
      <FileSizeInKB>176784</FileSizeInKB>
      <FileType>pdf</FileType>
      <ReportingPeriod>September</ReportingPeriod>
      <ReportingYear>2010</ReportingYear>
    </Primary>
  </Document>
</Transaction>

Объяснение изменений во входном XML: Предоставленный входной XML недопустим, поскольку вы используете двойные кавычки для каждого атрибута. Кроме того, префикс fun не объявлен для узла Document. Я изменил префикс fun на fun1 и привязал префикс на корневом уровне.


И эта таблица стилей:

<?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"/>

  <!-- This identity template copies the document -->
  <xsl:template match="node() | @*">
    <xsl:copy>
      <xsl:apply-templates select="node() | @*"/>
    </xsl:copy>
  </xsl:template>

  <!-- This template will only match the 'Primary' nodes
       and modify them the way you want. -->
  <xsl:template match="Primary">
    <xsl:copy>
      <xsl:apply-templates select="node() | @*"/>
      <!-- As you can see, this is the only difference
           between the identity template and this specific
           template. -->
      <xsl:copy-of select="../Country"/>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

Даст вам идентичный документ, но с копией Country в Primary:

<?xml version="1.0" encoding="UTF-8"?>
<Transaction xmlns:fun1="DocumentXML.com">
  <Date>2010-10-14T12:06:12.164+01:00</Date>
  <Production>NO</Production>
  <Document fun1:OID="1.9.101106">
      <DocumentType>Monthly A</DocumentType>
      <RangeName>Range Name</RangeName>
      <Name>Equity</Name>
      <Language>English</Language>
      <Class>A Acc</Class>
      <Active>YES</Active>
      <Country>UK</Country>
      <Country>Luxembourg</Country>
      <Country>Denmark</Country>
      <Country>Malta</Country>
      <Primary fun1:OID="1.9.101106">
         <Name>SISF-Indian-Equity-A-Acc-FMR-UKEN</Name>
         <FileSizeInKB>176784</FileSizeInKB>
         <FileType>pdf</FileType>
         <ReportingPeriod>September</ReportingPeriod>
         <ReportingYear>2010</ReportingYear>
         <Country>UK</Country>
         <Country>Luxembourg</Country>
         <Country>Denmark</Country>
         <Country>Malta</Country>
      </Primary>
      <Primary fun1:OID="1.9.101118">
         <Name>SISF-Indian-Equity-A-Acc</Name>
         <FileSizeInKB>176784</FileSizeInKB>
         <FileType>pdf</FileType>
         <ReportingPeriod>September</ReportingPeriod>
         <ReportingYear>2010</ReportingYear>
         <Country>UK</Country>
         <Country>Luxembourg</Country>
         <Country>Denmark</Country>
         <Country>Malta</Country>
      </Primary>
  </Document>
</Transaction>
1 голос
/ 01 декабря 2010

Просто для удовольствия, самая короткая таблица стилей:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
            <xsl:apply-templates select="self::Primary/../Country"/>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

Другие короче без изменения правила идентификации:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="node()|@*" name="identity">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="Primary/*[last()]">
        <xsl:call-template name="identity"/>
        <xsl:apply-templates select="../../Country"/>
    </xsl:template>
</xsl:stylesheet>

Примечание : оба не используют xsl:copy-of, но xsl:apply-templates. Это позволяет дальнейшую обработку.

0 голосов
/ 01 декабря 2010

хорошо, если вы используете xslt для генерации нового XML-документа, я просто создал бы документ, а затем для основного узла сделайте это

<xsl:for-each select="../Country">
<Country><xsl:value-of select="."/></Country>
</xsl:for-each>

, могут быть более простые способы достижения тех же результатов ..?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...