Скопировать подмножество ввода XML с помощью xslt - PullRequest
1 голос
/ 22 марта 2012

Мне нужен XSLT-файл для преобразования входного XML-файла в другой с подмножеством узлов входного XML-файла. Например, если на входе есть 10 узлов, мне нужно создать вывод примерно с 5 узлами. Входные

  <Department diffgr:id="Department1" msdata:rowOrder="0">
    <Department>10</Department>
    <DepartmentDescription>BABY PRODUCTS</DepartmentDescription>
    <DepartmentSeq>7</DepartmentSeq>
    <InsertDateTime>2011-09-29T13:19:28.817-05:00</InsertDateTime>
   </Department>

Выход:

  <Department diffgr:id="Department1" msdata:rowOrder="0">
    <Department>10</Department>
    <DepartmentDescription>BABY PRODUCTS</DepartmentDescription>
   </Department>

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

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:output omit-xml-declaration="yes"/>

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

  <xsl:template match="Department/DepartmentSeq"/>
  <xsl:template match="Department/InsertDateTime"/>

</xsl:stylesheet>

Мне нужен xslt, который помогает мне выбрать нужные мне узлы, а не «копировать все и отфильтровывать то, что мне не нужно», поскольку мне, возможно, придется менять свой xslt всякий раз, когда входная схема добавляет больше узлов.

Обновление:

Фрагмент, который я отправил, был взят из .NET Diffgram. Полный XML выглядит следующим образом

Введите:

<diffgr:diffgram xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" xmlns:diffgr="urn:schemas-microsoft-com:xml-diffgram-v1">
  <NewDataSet>
    <MessageHeader>
      <MessageID>201112270242029525719b93a-5fc5-42ce-8424-10764a4497ca</MessageID>
      <RequestType>Publish</RequestType>
      <ListOfApplications />
      <MessageType>MCH</MessageType>
    </MessageHeader>
    <Department diffgr:id="Department1" msdata:rowOrder="0">
      <Department>10</Department>
      <DepartmentDescription>BABY PRODUCTS</DepartmentDescription>
      <DepartmentSeq>7</DepartmentSeq>
      <InsertDateTime>2011-09-29T13:19:28.817-05:00</InsertDateTime>
      <UpdateDateTime>2011-09-30T11:50:59-05:00</UpdateDateTime>
      <InsertDateTimeUTC>2011-09-29T18:19:28.817-05:00</InsertDateTimeUTC>
    </Department>
    <Subclass diffgr:id="Subclass1" msdata:rowOrder="0" diffgr:hasChanges="modified">
      <Department>10</Department>
      <Category>03</Category>
      <Class>010</Class>
      <Subclass>03</Subclass>
      <SubclassLongDescription>BABY ACCESSORIES-OTHER LD TX 1120</SubclassLongDescription>
      <SubclassShortDescription>BABY ACCESSORIES-OTH</SubclassShortDescription>
    </Subclass>
  </NewDataSet>
  <diffgr:before>
    <Subclass diffgr:id="Subclass1" msdata:rowOrder="0">
      <Department>10</Department>
      <Category>03</Category>
      <Class>010</Class>
      <Subclass>03</Subclass>
      <SubclassLongDescription>BABY ACCESSORIES-OTHER LD TX 1120</SubclassLongDescription>
      <SubclassShortDescription>BABY ACCESSORIES-OTH</SubclassShortDescription>
    </Subclass>
  </diffgr:before>
</diffgr:diffgram>

С предоставленным Бородиным xslt, вот что я получаю

<diffgr:diffgram xmlns:diffgr="urn:schemas-microsoft-com:xml-diffgram-v1" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
  <NewDataSet>
    <MessageHeader>
      <MessageID>201112270242029525719b93a-5fc5-42ce-8424-10764a4497ca</MessageID>
      <RequestType>Publish</RequestType>
      <ListOfApplications />
      <MessageType>MCH</MessageType>
    </MessageHeader>
    <Department diffgr:id="Department1" msdata:rowOrder="0">
      <Department>10</Department>
      <DepartmentDescription>BABY PRODUCTS</DepartmentDescription>
    </Department>
    <Subclass diffgr:id="Subclass1" msdata:rowOrder="0" diffgr:hasChanges="modified">
      <Department>10</Department>
      <Category>03</Category>
      <Class>010</Class>
      <Subclass>03</Subclass>
      <SubclassLongDescription>BABY ACCESSORIES-OTHER LD TX 1120</SubclassLongDescription>
      <SubclassShortDescription>BABY ACCESSORIES-OTH</SubclassShortDescription>
    </Subclass>
  </NewDataSet>
  <diffgr:before>
    <Subclass diffgr:id="Subclass1" msdata:rowOrder="0">
      <Department>10</Department>
      <Category>03</Category>
      <Class>010</Class>
      <Subclass>03</Subclass>
      <SubclassLongDescription>BABY ACCESSORIES-OTHER LD TX 1120</SubclassLongDescription>
      <SubclassShortDescription>BABY ACCESSORIES-OTH</SubclassShortDescription>
    </Subclass>
  </diffgr:before>
</diffgr:diffgram>

Я не хочу ничего, кроме этих тегов Department и DescriptionDescription. Почему копируются другие узлы MessageHeader / подкласс, если они не указаны в xslt?

Может кто-нибудь дать мне лучшее решение, чем указано выше. Добавление каждого узла, как это, довольно утомительно, но работает, если больше ничего не возможно.

Ответы [ 4 ]

2 голосов
/ 22 марта 2012

Я предлагаю вам использовать преобразование идентичности со специальным правилом для обработки <Department> элементов, которое позволяет вам указать, какой из его дочерних элементов вы хотите скопировать.Вот пример кода.

<?xml version="1.0" encoding="UTF-8" ?>

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:output method="xml" indent="yes"/>

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

  <xsl:template match="Department[Department]">
    <xsl:copy>
      <xsl:apply-templates select="@*|Department|DepartmentDescription" />
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

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

<?xml version="1.0" encoding="utf-8"?>
<diffgr:diffgram xmlns:diffgr="urn:schemas-microsoft-com:xml-diffgram-v1" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">

   <NewDataSet>

      <Department diffgr:id="Department1" msdata:rowOrder="0">
         <Department>10</Department>
         <DepartmentDescription>BABY PRODUCTS</DepartmentDescription>
      </Department>

   </NewDataSet>

</diffgr:diffgram>
1 голос
/ 22 марта 2012

Если вы хотите сопоставлять только определенные узлы, в отличие от предоставления списка исключений, вы можете просто ввести требуемый список имен элементов

<xsl:template match="Department|DepartmentSeq|InsertDateTime|@*">

Итак, учитывая следующее XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:output omit-xml-declaration="yes"/>
   <xsl:template match="Department|DepartmentSeq|InsertDateTime|@*">
      <xsl:copy>
         <xsl:apply-templates select="node()|@*"/>
      </xsl:copy>
   </xsl:template>

   <xsl:template match="*" />
</xsl:stylesheet>

Применительно к следующему XML (я убрал префиксы пространства имен для упрощения)

<Department id="Department1" rowOrder="0">
   <Department>10</Department>
   <DepartmentDescription>BABY PRODUCTS</DepartmentDescription>
   <DepartmentSeq>7</DepartmentSeq>
   <InsertDateTime>2011-09-29T13:19:28.817-05:00</InsertDateTime>
</Department>

Выводится следующее. Обратите внимание, что атрибуты сохраняются с помощью @ * match.

<Department id="Department1" rowOrder="0">
   <Department>10</Department>
   <DepartmentSeq>7</DepartmentSeq>
   <InsertDateTime>2011-09-29T13:19:28.817-05:00</InsertDateTime>
</Department>

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

<xsl:template match="*" />
0 голосов
/ 17 июня 2012
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:diffgr="urn:schemas-microsoft-com:xml-diffgram-v1">
 <xsl:output indent="yes"/><xsl:strip-space elements="*"/>

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

  <!-- shutup unwanted elements -->
  <xsl:template match="MessageHeader
        | Subclass
        | InsertDateTime
        | UpdateDateTime
        | InsertDateTimeUTC
        | DepartmentSeq
        | diffgr:before"/>

 </xsl:stylesheet>
0 голосов
/ 30 марта 2012

Это решение работало лучше всего для моего ввода

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

  </xsl:template>
  <xsl:template match="*" />

</xsl:stylesheet>

Однако я обнаружил, что писать соответствие для каждого узла в иерархии очень громоздко. Тем не менее, работает, лучшие решения приветствуются!

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