Фильтр атрибутов с использованием XSLT на основе имен атрибутов - PullRequest
2 голосов
/ 02 января 2012

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

<RootList>
<Root RootAtt1="1" RootAtt2="2" RootAtt3="3">
<Extn ExtnAtt1="1">
<Child ChildAtt1="1" ChildAtt2="2"/>
</Extn>
</Root>
</RootList>

Что мне нужно, так это если какой-либо дополнительный атрибут поставляется с этим XML-файлом в узле RootList \ Root \ Extn помимо того, что присутствует, этот атрибут будет удален.

Так что, если ввод идет как:

<RootList>
<Root RootAtt1="1" RootAtt2="2" RootAtt3="3">
<Extn ExtnAtt1="1" ExtnAtt2="2">
<Child ChildAtt1="1" ChildAtt2="2"/>
</Extn>
</Root>
</RootList>

тогда результат будет выглядеть так:

<RootList>
<Root RootAtt1="1" RootAtt2="2" RootAtt3="3">
<Extn ExtnAtt1="1">
<Child ChildAtt1="1" ChildAtt2="2"/>
</Extn>
</Root>
</RootList>

Для этого я написал xsl как:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
   <xsl:output method="xml" indent="yes"/> 
<xsl:template match="/">
<xsl:apply-templates/>

<RootList>
<xsl:for-each select="/RootList">
<xsl:element name="Root">
<xsl:element name="Extn">
<xsl:attribute name="ExtnAtt1">
<xsl:value-of select="/RootList/Root/Extn/@ExtnAtt1"/>
</xsl:attribute>
</xsl:element>
</xsl:element>
</xsl:for-each>
</RootList>
</xsl:template>
</xsl:stylesheet>

Но это дает мне вывод:

<?xml version="1.0" encoding="UTF-16"?>
<RootList>
<Root>
<Extn ExtnAtt1="1" />
</Root>
</RootList>

Я хочу сохранить существующий xml и удалить только лишние атрибуты.

Может кто-нибудь, пожалуйста, помогите мне с этим.

Заранее спасибо, ребята.

Спасибо, ребята, за все ответы ... вы, ребята, молодцы .... Я понял другой метод .... дайте мне знать, что вы думаете об этом ....

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
   <xsl:output method="xml" indent="yes"/> 
<xsl:template match="/">
<xsl:apply-templates/>
<RootList>
<xsl:for-each select="/RootList">
<xsl:element name="Root">
<xsl:copy-of select="/RootList/Root/@RootAtt1"/>
<xsl:copy-of select="/RootList/Root/@RootAtt2"/>
<xsl:copy-of select="/RootList/Root/@RootAtt3"/>
<xsl:element name="Extn">
<xsl:copy-of select="/RootList/Root/Extn/@ExtnAtt1"/>
<xsl:element name="Child">
<xsl:copy-of select="/RootList/Root/Extn/Child/@ChildAtt1"/>
<xsl:copy-of select="/RootList/Root/Extn/Child/@ChildAtt2"/>
</xsl:element>
</xsl:element>
</xsl:element>
</xsl:for-each>
</RootList>
</xsl:template>
</xsl:stylesheet>

Когда это применяется к:

<RootList>
<Root RootAtt1="1" RootAtt2="2" RootAtt3="3">
<Extn ExtnAtt1="1" ExtnAtt2="2">
<Child ChildAtt1="1" ChildAtt2="2"/>
</Extn>
</Root>
</RootList>

Это дает вывод как:

<?xml version="1.0" encoding="UTF-16"?>
<RootList>
<Root RootAtt1="1" RootAtt2="2" RootAtt3="3">
<Extn ExtnAtt1="1">
<Child ChildAtt1="1" ChildAtt2="2" />
</Extn>
</Root>
</RootList>

при условии, что RootList \ Root \ Extn \ @ ExtnAtt2 является нежелательным атрибутом.

Спасибо Жду вашего ответа ....:)

Приветствия

Ответы [ 3 ]

2 голосов
/ 02 января 2012

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

<xsl:template match="Extn/@*[not(local-name() = 'ExtnAtt1')]" />

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

<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="Extn/@*[not(local-name() = 'ExtnAtt1')]"/>
</xsl:stylesheet>

Применительно к следующему XML

<RootList>   
  <Root RootAtt1="1" RootAtt2="2" RootAtt3="3">   
    <Extn ExtnAtt1="1" ExtnAtt2="2">   
      <Child ChildAtt1="1" ChildAtt2="2"/>   
    </Extn>   
  </Root>   
</RootList> 

Будет выведено следующее:

<RootList>
  <Root RootAtt1="1" RootAtt2="2" RootAtt3="3">
    <Extn ExtnAtt1="1">
      <Child ChildAtt1="1" ChildAtt2="2"></Child>
    </Extn>
  </Root>
</RootList>

Альтернативный метод, если вам требуется сохранить несколько атрибутов в элементе Extn , состоит в том, чтобы использовать таблицу стилей, например, которая явно перечисляет сохраняемые атрибуты:

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

   <xsl:template match="Extn">
      <xsl:copy>
         <xsl:apply-templates select="@ExtnAtt1|@ExtnAtt3|@ExtnAtt5|node()"/>
      </xsl:copy>
   </xsl:template>

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

Применительно к следующему XML

<RootList>
  <Root RootAtt1="1" RootAtt2="2" RootAtt3="3">
    <Extn ExtnAtt1="1" ExtnAtt2="2" ExtnAtt3="3" ExtnAtt4="4" ExtnAtt5="5">
      <Child ChildAtt1="1" ChildAtt2="2"/>
    </Extn>
  </Root>
</RootList>

Выводится следующее

<RootList>
  <Root RootAtt1="1" RootAtt2="2" RootAtt3="3">
    <Extn ExtnAtt1="1" ExtnAtt3="3" ExtnAtt5="5">
      <Child ChildAtt1="1" ChildAtt2="2"></Child>
    </Extn>
   </Root>
</RootList>

Обратите внимание, что все остальные элементы, кроме элемента Extn , остаются без изменений.

0 голосов
/ 02 января 2012

Вот решение true , которое в отличие от принятого в настоящее время работает с любым количеством атрибутов для элементов "строгого" документа :

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

 <my:strict>
    <RootList>
        <Root RootAtt1="1" RootAtt2="2" RootAtt3="3">
            <Extn ExtnAtt1="1" ExtnAtt3="1">
                <Child ChildAtt1="1" ChildAtt2="2"/>
            </Extn>
        </Root>
    </RootList>
 </my:strict>

 <xsl:variable name="vStrict"
      select="document('')/*/my:strict"/>

 <xsl:template match="/">
  <xsl:apply-templates select="*">
      <xsl:with-param name="pstrictElement"
        select="$vStrict/*"/>
  </xsl:apply-templates>
 </xsl:template>

 <xsl:template match="*">
   <xsl:param name="pstrictElement"/>
     <xsl:copy>
       <xsl:apply-templates select="@*">
        <xsl:with-param name="pstrictElement"
             select="$pstrictElement"/>
       </xsl:apply-templates>

       <xsl:apply-templates select="*[1]">
        <xsl:with-param name="pstrictElement"
             select="$pstrictElement/*[1]"/>
       </xsl:apply-templates>

       <xsl:apply-templates select="following-sibling::*[1]">
        <xsl:with-param name="pstrictElement"
             select="$pstrictElement/following-sibling::*[1]"/>
       </xsl:apply-templates>
     </xsl:copy>
 </xsl:template>

 <xsl:template match="@*">
   <xsl:param name="pstrictElement"/>

    <xsl:copy-of select=
    "self::node()
       [$pstrictElement/@*[name() = name(current())]]"/>
 </xsl:template>
</xsl:stylesheet>

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

<RootList>
    <Root RootAtt1="1" RootAtt2="2" RootAtt3="3">
        <Extn ExtnAtt1="1" ExtnAtt2="1" ExtnAtt3="1" ExtnAtt4="1">
            <Child ChildAtt1="1" ChildAtt2="2"/>
        </Extn>
    </Root>
</RootList>

желаемый, правильный, очищенный результат получается :

<RootList>
   <Root RootAtt1="1" RootAtt2="2" RootAtt3="3">
      <Extn ExtnAtt1="1" ExtnAtt3="1">
         <Child ChildAtt1="1" ChildAtt2="2"/>
      </Extn>
   </Root>
</RootList>
0 голосов
/ 02 января 2012
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
>
<xsl:output method="xml" indent="yes"/>

<xsl:template match="RootList">
<xsl:apply-templates select="Root"/>
</xsl:template>

<xsl:template match="Root | Extn | Child">
<xsl:copy>
<xsl:apply-templates select="@RootAtt1 | @RootAtt2 | @RootAtt3 | @ExtnAtt1 | @ChildAtt1 | @ChildAtt2" />
<xsl:apply-templates select="Root | Extn | Child"/>
</xsl:copy>
</xsl:template>


<xsl:template match="@RootAtt1 | @RootAtt2 | @RootAtt3 | @ExtnAtt1 | @ChildAtt1 | @ChildAtt2">
<xsl:copy-of select="."/>
</xsl:template>
</xsl:stylesheet>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...