Эффективный способ отфильтровать часть XML-документа - PullRequest
2 голосов
/ 05 ноября 2010

Я ищу эффективный способ фильтрации XML-документа.Я использую C # /. NET.Скажем, у меня есть следующий оригинальный документ:

<Bookstores>
   <Bookstore>
      <StoreName>Store 1</StoreName>
      <Books>
         <Book>
            <Author>Bob</Author>
            <Title>ABC</Title>
         </Book> 
         <Book>
            <Author>John</Author>
            <Title>XYZ</Title>
         </Book> 
      </Books>
   </Bookstore>
</Bookstores>

У меня есть другой частичный документ, хранящийся где-то еще:

<Book>
   <Author>John</Author>
   <Title>XYZ</Title>
</Book> 

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

<Bookstores>
   <Bookstore>
      <StoreName>Store 1</StoreName>
      <Books>
         <Book>
            <Author>John</Author>
            <Title>XYZ</Title>
         </Book> 
      </Books>
   </Bookstore>
</Bookstores>

Я также открыт для других способов, которыми я мог бы сделать это.У меня есть оригинальный документ, которым я не могу манипулировать напрямую.Мне нужно хранить «ссылку» на часть (и) этого документа отдельно.А затем мне нужно отфильтровать / перевести исходный документ, используя «ссылку» для отображения.

Ответы [ 2 ]

4 голосов
/ 05 ноября 2010

Это XSLT-преобразование :

<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:variable name="vrtfReference">
     <Book>
       <Author>John</Author>
       <Title>XYZ</Title>
     </Book>
 </xsl:variable>

 <xsl:variable name="vReference" select=
 "document('')/*/xsl:variable
                  [@name='vrtfReference']/*"/>

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

 <xsl:template match="Book">

   <xsl:apply-templates mode="copy" select=
    "self::node()[$vReference
                   [Author = current()/Author
                  and
                   Title = current()/Title
                   ]
                  ]
    "/>
 </xsl:template>

 <xsl:template match="node()" mode="copy">
  <xsl:call-template name="identity"/>
 </xsl:template>
</xsl:stylesheet>

при применении к предоставленному документу XML :

<Bookstores>
   <Bookstore>
      <StoreName>Store 1</StoreName>
      <Books>
         <Book>
            <Author>Bob</Author>
            <Title>ABC</Title>
         </Book>
         <Book>
            <Author>John</Author>
            <Title>XYZ</Title>
         </Book>
      </Books>
   </Bookstore>
</Bookstores>

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

<Bookstores>
   <Bookstore>
      <StoreName>Store 1</StoreName>
      <Books>
         <Book>
            <Author>John</Author>
            <Title>XYZ</Title>
         </Book>
      </Books>
   </Bookstore>
</Bookstores>

Примечание :

  1. Правило идентификации используется для копирования любого узла«как есть» , за исключением Book элементов, которые не соответствуют идентичным Book элементам в справочном документе.

  2. Соответствующий шаблон Bookрешает скопировать текущий узел (применяя к нему правило идентификации) , только если оба дочерних элемента (Author и Title) имеют то же значение, что и дочерние элементы некоторого элемента Book из ссылкидокумент .

  3. Просто для удобства я включил справочный документ в таблицу стилей XSLT .На практике это будет в своем собственном XML-файле, и для этого потребуется лишь небольшое изменение в определении переменной $vReference.

1 голос
/ 05 ноября 2010

Попробуйте LINQ to XML, http://www.hookedonlinq.com/LINQtoXML5MinuteOverview.ashx.

Надеюсь, это поможет.

...