AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / coding / Perguntas / 79559541
Accepted
Kishieel
Kishieel
Asked: 2025-04-07 17:50:09 +0800 CST2025-04-07 17:50:09 +0800 CST 2025-04-07 17:50:09 +0800 CST

Como armazenar metadados ocultos e persistentes em arquivos DOCX que sobrevivem a edições

  • 772

Estou procurando uma maneira de adicionar metadados legíveis por máquina aos relatórios DOCX que gero. O objetivo é permitir que os usuários modifiquem os estilos do documento e o carreguem novamente no sistema, preservando os metadados.

Na primeira tentativa, ingenuamente tentei armazenar os metadados nos comentários, mas notei que alguns editores, especificamente o Microsoft Word, removem meus comentários e geram um arquivo DOCX sem eles após a modificação.

Também experimentei tags de documentos estruturados, mas tanto o Google Docs quanto o Microsoft Word as removem após a modificação de estilos.

Por fim, tentei usar XML personalizado, mas tanto o Google Docs quanto o Microsoft Word removeram os atributos e tags que adicionei.

Pesquisei bastante, mas não encontrei nenhuma solução que funcionasse. Alguém já passou por um problema semelhante e pode dar algum conselho?

PS1

Como há muitas linhas mesmo em arquivos DOCX pequenos, criei um repositório minimalista para mostrar melhor o que tentei até agora. Cada tentativa é colocada em um diretório separado. Cada diretório contém:

  • Document.docx — o arquivo base criado manualmente com alguns metadados ocultos.
  • ModifiedWithGoogle.docx e ModifiedWithWord.docx — o resultado após a edição do documento no Google Docs ou no Microsoft Word.
  • Conteúdo descompactado de cada arquivo .docx para facilitar a inspeção do XML interno.

Repositório: https://github.com/kishieel/docx-metadata

Na primeira tentativa, adicionei metadados usando comentários. Isso funcionou bem com o Google Docs, onde os comentários foram preservados mesmo quando o texto foi movido usando recortar e colar. No entanto, o Microsoft Word removeu todos os comentários. Talvez o Word espere uma maneira diferente de criar comentários?

Exemplo de entrada:

<!-- 1_comments/Document/word/document.xml -->
<w:document ...>
  <w:body>
    <w:p>
      <w:commentRangeStart w:id="0" />
      <w:r>
        <w:t xml:space="preserve">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris quis mollis tellus. Aenean at maximus nunc.</w:t>
      </w:r>
      <w:commentRangeEnd w:id="0" />
    </w:p>
  </w:body>
</w:document>
<!-- 1_comments/Document/word/comments.xml -->
<w:comments ...>
  <w:comment w:id="0" w:date="2025-04-07T09:10:21.783Z">
    <w:p>
      <w:r>
        <w:t xml:space="preserve">Some metadata #1</w:t>
      </w:r>
    </w:p>
  </w:comment>
</w:comments>

Na segunda abordagem, tentei usar SDTs. Nesse caso, o Microsoft Word os preservou (embora tenha dividido cada frase em palavras separadas, o que pode ser o comportamento padrão ou algo ter dado errado). O Google Docs os removeu completamente do arquivo modificado.

Exemplo de entrada:

<!-- 2_structured_document_tags/Document/word/document.xml -->
<w:document ...>
  <w:body>
    <w:p>
      <w:sdt>
        <w:sdtPr>
          <w:tag w:val="Some metadata #1" />
          <w:alias w:val="Some alias #1" />
        </w:sdtPr>
        <w:sdtContent>
          <w:r>
            <w:t xml:space="preserve">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris quis mollis tellus. Aenean at maximus nunc.</w:t>
          </w:r>
        </w:sdtContent>
      </w:sdt>
    </w:p>
  </w:body>
</w:document>

Fornecerei o exemplo XML personalizado quando estiver pronto.

ms-word
  • 1 1 respostas
  • 57 Views

1 respostas

  • Voted
  1. Best Answer
    jonsson
    2025-04-09T18:28:10+08:002025-04-09T18:28:10+08:00

    Não tenho experiência real recente na preservação de metadados por meio das três coisas que você mencionou (Microsoft Word, Google Docs e LibreOffice Writer), mas tentei várias abordagens para armazenar material que conheço no Word.

    Para testes, tenho usado Microsoft 365 MSO (Version 2503 Build 16.0.18623.20116) 64-biton Windows 10, L ibreOffice Writer Version: 24.2.7.2 (X86_64) / LibreOffice Communit Build ID: 420(Build:2)on Linux, e a versão gratuita atual do Google Docs(não sei se o Google tem uma versão paga mais capaz). Crio documentos diretamente no Word, usando VBA quando necessário, por exemplo, para adicionar uma Parte XML Personalizada ou Variável de Documento. Nunca tentei salvar ou baixar em qualquer formato diferente de .docx. Há bastante documentação sobre o formato .docx e alguma documentação muito boa da MS sobre a implementação do Word, mas não procurei documentação equivalente para o Google Docs e o LibreOffice. Você provavelmente precisa saber quais recursos a MS, o LibreOffice e o Google "oficialmente suportam"

    Os tipos de recursos disponíveis no Word para armazenar metadados são "em todo o documento" ou "associados a um local no documento". Para "em todo o documento", existem

    • Partes XML personalizadas (não visíveis ou alteráveis ​​por meio da interface do usuário, mas os valores podem ser exibidos usando controles de conteúdo)
    • Variáveis ​​de documento (não visíveis ou alteráveis ​​por meio da IU, mas os valores podem ser exibidos usando { DOCVARIABLE }campos
    • Propriedades de documentos personalizadas (podem ser vistas e modificadas na interface do usuário por meio da guia Informações do arquivo, e os valores podem ser exibidos usando { DOCPROPERTY }campos).

    Para "associado a um local no texto", você poderia, em princípio, usar pelo menos o seguinte:

    • Texto oculto
    • Comentários (visíveis)
    • Notas de rodapé (visíveis)
    • Notas de rodapé (visíveis)
    • Controles de conteúdo (visíveis) potencialmente mapeados para partes XML personalizadas
    • { DOCPROPERTY }campos com Propriedades de Documento Personalizadas (visíveis)
    • { DOCVARIABLE }campos com variáveis ​​de documento (visíveis)
    • { SET }campos (podem ser visíveis, dependendo das configurações e ações do usuário), por exemplo

    { SET ABookMarkName "to some metadata" }

    Sei que você tentou Comentários e acho que eles podem funcionar, apesar do que você encontrou, mas não acho que sejam tão fáceis de manter ocultos. Texto oculto, notas de rodapé, notas de fim ou Controles de Conteúdo também não são, então não usei nenhum deles. Além disso, muitas notas de rodapé ou notas de fim tendem a interferir no layout do documento.

    O LibreOffice completou com sucesso a maioria dos Othings que tentei no Word. No entanto, ele exibiu uma caixa de diálogo do tipo "algumas dessas coisas podem não ser salvas corretamente" ao salvar.

    O Google Docs perdeu a maioria das coisas que tentei, mas preservou pelo menos Comentários, Propriedades Personalizadas do Documento e até mesmo os { DOCPROPERTY }campos necessários para inserir esses valores no documento. Ele removeu:

    • Partes XML personalizadas
    • Controles de conteúdo
    • Variáveis ​​de Documento
    • { DOCVARIABLE }códigos de campo
    • { SET }códigos de campo

    O que me sugere que a única coisa com boas chances de funcionar com o Google Docs são as Propriedades Personalizadas de Documentos. Elas têm limitações (acho que há um limite para o número que você pode ter, e para o comprimento por Propriedade ou para o comprimento total).

    Para metadados de "nível de documento", talvez seja necessário dividir seus dados em pedaços menores.

    Para metadados "posicionais", pode haver um problema com esses máximos. Mesmo que não seja o caso, marcar a posição usando o { DOCPROPERTY }campo apropriado significa que você exibe o valor da propriedade — se não quiser fazer isso, provavelmente terá que fazer algo assim:

    • Tenha uma propriedade chamada myprop (digamos) contendo o valor real da propriedade.
    • Tenha outra propriedade com um nome relacionado, mymark (por exemplo), com um espaço como conteúdo (a menor Propriedade de Documento Personalizada que você pode ter no Word)
    • Use { DOCPROPERTY mymark }para marcar o local, assim você terá apenas um resultado com um único espaço.

    No Word, é possível usar o fato de que o Word não é muito exigente com informações extras em códigos de campo, então você poderia ter uma única propriedade em branco chamada blank e um código de campo { DOCPROPERTY blank myprop }, mas infelizmente o Google Docs removerá a parte "myprop".

    E é basicamente isso.

    Apenas para cobrir alguns dos pontos que levantei originalmente nos Comentários:

    No seu exemplo "comments_1", o motivo pelo qual nenhum comentário aparece no Word na versão inicial (o código XML que você postou e o Document.docx relacionado) é porque o Word precisa de um elemento <w:commentReference> para que os comentários apareçam na interface do usuário.

    por exemplo, se você alterar a marcação que você postou na sua pergunta para isso e recriar o .docx, você deverá ver o primeiro comentário ao abrir o .docx no Word.

    <w:document ...>
      <w:body>
        <w:p>
          <w:commentRangeStart w:id="0" />
          <w:r>
            <w:t xml:space="preserve">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris quis mollis tellus. Aenean at maximus nunc.</w:t>
          </w:r>
          <w:commentRangeEnd w:id="0" />
          <w:r>
            <w:rPr>
              <w:rStyle w:val="CommentReference"/>
            </w:rPr>
            <w:commentReferenceThe version of LibreOffice I have here does display the comments even
     w:id="0"/>
          </w:r>
        </w:p>
      </w:body>
    </w:document>
    

    (Você não precisa ter o <w:rPr>elemento, mas o Word insere um).

    Como mencionei originalmente em um comentário à sua pergunta, o motivo pelo qual seu 1_comments.docx não abre é porque o arquivo docProps/custom.xml contém dois elementos com o mesmo FMTID e nome (o que não é permitido). Ele também tem quase 600 caracteres, mas embora eu achasse que o Word tinha um limite de 255 caracteres para uma propriedade de documento personalizada, ele não parece apresentar erros ou truncar.

    Então, aqui, também alterei custom.xml para o seguinte para corrigir isso:

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <Properties xmlns="http://schemas.openxmlformats.org/officeDocument/2006/custom-properties" 
      xmlns:vt="http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes">
      <property fmtid="{D5CDD505-2E9C-101B-9397-08002B2CF9AE}" pid="2" name="xbrl">
        <vt:lpwstr>abc</vt:lpwstr>
      </property>
    </Properties>
    
    • 1

relate perguntas

  • Como converter texto em hiperlinks sem VBA?

  • MS Word mostrando dois conjuntos diferentes de índice integrado

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Reformatar números, inserindo separadores em posições fixas

    • 6 respostas
  • Marko Smith

    Por que os conceitos do C++20 causam erros de restrição cíclica, enquanto o SFINAE antigo não?

    • 2 respostas
  • Marko Smith

    Problema com extensão desinstalada automaticamente do VScode (tema Material)

    • 2 respostas
  • Marko Smith

    Vue 3: Erro na criação "Identificador esperado, mas encontrado 'import'" [duplicado]

    • 1 respostas
  • Marko Smith

    Qual é o propósito de `enum class` com um tipo subjacente especificado, mas sem enumeradores?

    • 1 respostas
  • Marko Smith

    Como faço para corrigir um erro MODULE_NOT_FOUND para um módulo que não importei manualmente?

    • 6 respostas
  • Marko Smith

    `(expression, lvalue) = rvalue` é uma atribuição válida em C ou C++? Por que alguns compiladores aceitam/rejeitam isso?

    • 3 respostas
  • Marko Smith

    Um programa vazio que não faz nada em C++ precisa de um heap de 204 KB, mas não em C

    • 1 respostas
  • Marko Smith

    PowerBI atualmente quebrado com BigQuery: problema de driver Simba com atualização do Windows

    • 2 respostas
  • Marko Smith

    AdMob: MobileAds.initialize() - "java.lang.Integer não pode ser convertido em java.lang.String" para alguns dispositivos

    • 1 respostas
  • Martin Hope
    Fantastic Mr Fox Somente o tipo copiável não é aceito na implementação std::vector do MSVC 2025-04-23 06:40:49 +0800 CST
  • Martin Hope
    Howard Hinnant Encontre o próximo dia da semana usando o cronógrafo 2025-04-21 08:30:25 +0800 CST
  • Martin Hope
    Fedor O inicializador de membro do construtor pode incluir a inicialização de outro membro? 2025-04-15 01:01:44 +0800 CST
  • Martin Hope
    Petr Filipský Por que os conceitos do C++20 causam erros de restrição cíclica, enquanto o SFINAE antigo não? 2025-03-23 21:39:40 +0800 CST
  • Martin Hope
    Catskul O C++20 mudou para permitir a conversão de `type(&)[N]` de matriz de limites conhecidos para `type(&)[]` de matriz de limites desconhecidos? 2025-03-04 06:57:53 +0800 CST
  • Martin Hope
    Stefan Pochmann Como/por que {2,3,10} e {x,3,10} com x=2 são ordenados de forma diferente? 2025-01-13 23:24:07 +0800 CST
  • Martin Hope
    Chad Feller O ponto e vírgula agora é opcional em condicionais bash com [[ .. ]] na versão 5.2? 2024-10-21 05:50:33 +0800 CST
  • Martin Hope
    Wrench Por que um traço duplo (--) faz com que esta cláusula MariaDB seja avaliada como verdadeira? 2024-05-05 13:37:20 +0800 CST
  • Martin Hope
    Waket Zheng Por que `dict(id=1, **{'id': 2})` às vezes gera `KeyError: 'id'` em vez de um TypeError? 2024-05-04 14:19:19 +0800 CST
  • Martin Hope
    user924 AdMob: MobileAds.initialize() - "java.lang.Integer não pode ser convertido em java.lang.String" para alguns dispositivos 2024-03-20 03:12:31 +0800 CST

Hot tag

python javascript c++ c# java typescript sql reactjs html

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve