• Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
    Dedicated community for Japanese speakers
  • 한국 커뮤니티
    Dedicated community for Korean speakers
Exit
0

Get IHyperlink from IIDXMLElement

Explorer ,
Feb 20, 2022 Feb 20, 2022

Copy link to clipboard

Copied

Hi,

 

I have a very simple test document with only one hyperlink.

screenshot.png


I tried to to get IHyperlink via IHyperlinkSource but I got always NULL value for QueryHyperlinkSourceAt function.
textValue is correct so I think the dataModel and range.Start() parameter is right for QueryHyperlinkSourceAt function.

To get hyperlinks by IHyperlinktable is not solution for me because I would like to change the destination URL by en XML attribute "hyperlinkpattern" so I need to get IHyperlink via IIDXMLElement.

 

My code:

XMLReference xmlref = iter->first;
InterfacePtr<IIDXMLElement> elem(xmlref.Instantiate());
WideString elemName = elem->GetTagString();
WideString hyperlinkPattern = elem->GetAttributeValue(WideString("hyperlinkpattern"));

do {
	XMLContentIterator iter(elem->begin());
	InDesign::TextRange range = *iter;

	if (!range.IsValid()) {
		break;
	}

	InterfacePtr<ITextModel> textModel(range.QueryModel());
	if (!textModel) {
		break;
	}

	WideString textValue("");
	TextIterator begin_(textModel, range.Start());
	TextIterator end_(textModel, range.End());
	for (TextIterator iterText = begin_; iterText != end_; iterText++) {
		const UTF32TextChar characterCode = *iterText;
		textValue.Append(characterCode);
	}

	InterfacePtr<IHyperlinkSource> hyperlinkSource(static_cast<IHyperlinkSource*>(Utils<IHyperlinkUtils>()->QueryHyperlinkSourceAt(textModel, range.Start())));
	if (!hyperlinkSource)   // <------------------ hyperlinkSource ALWAYS NULL
		break;
	InterfacePtr<IHyperlink> hyperlink(db, hyperlinkSource->GetOwningHyperlink(), IID_IHYPERLINK);

	InterfacePtr<IHyperlinkDestination> hyperlinkDestination(db, hyperlink->GetDestinationUID(), IID_IHYPERLINKDESTINATION);
	hyperlinkDestination->SetName(PMString("https://adobe.com")); // Redirect URL to adobe 
} while (kFalse);

 

I appreciate any help.

Thx
Karoly

TOPICS
How to , SDK

Views

276

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines

correct answers 1 Correct answer

Community Expert , Feb 20, 2022 Feb 20, 2022

The following seems to work. Lot of work to find this(terse documentation to bless). This gives the idea, you can see if you get a more concise way of doing it. I have harcoded the query path for XMLElement, you can plug it with your code. One interesting thing is that even though the name is changed, it's not reflected on the hyperlinks panel even though querying it gives the chaged name.

            InterfacePtr<IIDXMLElement> rootXMLElement(Utils<IXMLUtils>()->QueryRootElement(Utils<ILayoutUI
...

Votes

Translate

Translate
Community Expert ,
Feb 20, 2022 Feb 20, 2022

Copy link to clipboard

Copied

Hi Karoly,

Looking at your document I see that you have hyperlink on the textframe and not on the text inside it and hence the code fails. If you select the text inside the box and then apply hyperlink to it then hopefully it will work

-Manan

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Feb 20, 2022 Feb 20, 2022

Copy link to clipboard

Copied

Hi Manan,

 

Thank you for your quick answer.

I will try it and let you know .

/Karoly

 

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Feb 20, 2022 Feb 20, 2022

Copy link to clipboard

Copied

The following seems to work. Lot of work to find this(terse documentation to bless). This gives the idea, you can see if you get a more concise way of doing it. I have harcoded the query path for XMLElement, you can plug it with your code. One interesting thing is that even though the name is changed, it's not reflected on the hyperlinks panel even though querying it gives the chaged name.

            InterfacePtr<IIDXMLElement> rootXMLElement(Utils<IXMLUtils>()->QueryRootElement(Utils<ILayoutUIUtils>()->GetFrontDocument()));
            ASSERT(rootXMLElement);
            if(!rootXMLElement)
                break;
        
            IIDXMLElement *elem = rootXMLElement->GetNthChild(0).Instantiate()->GetNthChild(0).Instantiate()->GetNthChild(0).Instantiate();
            do {
                XMLContentIterator iter(elem->begin());
                InDesign::TextRange range = *iter;
                if (!range.IsValid()) {
                    break;
                }
                InterfacePtr<ITextModel> textModel(range.QueryModel());
                if (!textModel) {
                    break;
                }
                
                InterfacePtr<IFrameList> iFrameList(textModel->QueryFrameList());
                if(!iFrameList)
                    break;
                
                InterfacePtr<ITextFrameColumn> iTextFrameColumn(iFrameList->QueryNthFrame(0));
                if(!iTextFrameColumn)
                    break;
                
                InterfacePtr<IMultiColumnTextFrame> iMultiColumnTextFrame(iTextFrameColumn->QueryMultiColumnTextFrame());
                if(!iMultiColumnTextFrame)
                    break;
                
                InterfacePtr<IHierarchy> iHierarchy(iMultiColumnTextFrame, UseDefaultIID());
                if(!iHierarchy)
                    break;
                
                InterfacePtr<IHyperlinkPageItemData> iHyperlinkPageItemData(iHierarchy->QueryParent(), UseDefaultIID());
                if(!iHyperlinkPageItemData)
                    break;
                
                InterfacePtr<IHyperlinkSource> iHyperlinkSource(::GetDataBase(iHierarchy), iHyperlinkPageItemData->GetSource(), UseDefaultIID());
                if(!iHyperlinkSource)
                    break;
                
                InterfacePtr<IHyperlink> iHyperlink(::GetDataBase(iHierarchy), iHyperlinkSource->GetOwningHyperlink(), UseDefaultIID());
                if(!iHyperlinkSource)
                    break;
                
                InterfacePtr<IHyperlinkDestination> hyperlinkDestination(::GetDataBase(iHierarchy), iHyperlink->GetDestinationUID(), UseDefaultIID());
                PMString name;
                hyperlinkDestination->GetName(&name);
                CAlert::InformationAlert(name);
                hyperlinkDestination->SetName(PMString("https://adobe.com")); // Redirect URL to adobe

 -Manan

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Feb 20, 2022 Feb 20, 2022

Copy link to clipboard

Copied

Great job!
Thank you!

/Karoly

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guide ,
Feb 21, 2022 Feb 21, 2022

Copy link to clipboard

Copied

I'd guess the name will be changed if you use a kChangeHyperlinkCmdBoss for the setter.

It will notify selection attribute changes for suite IID_IHYPERLINKSUITE.

That command will also trigger preflight ...

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Feb 21, 2022 Feb 21, 2022

Copy link to clipboard

Copied

Yeah I was getting an assert for direct change to database so the next action items was looking for the command. But I had already spent too much energy looking for the wherabouts of IHyperlinkPageItemData interface in the scheme of things. In the latest SDK's they have removed the information as to which boss class includes a particular interface. It's one hell of a task to look around.

-Manan

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Feb 22, 2022 Feb 22, 2022

Copy link to clipboard

Copied

LATEST

Hi Manan and Dirk,

 

To manipulate destination URL (IHyperlinkDestination) I used Facade::IHyperlinkFacade.

UID destUID = ::GetUIDRef(hyperlinkDestination).GetUID();
UIDRef destinationUIDRef = ::GetUIDRef(hyperlinkDestination);
hyperlinkDestination->SetName(URL);
status = Utils<Facade::IHyperlinkFacade>()->ChangeHyperlinkURLDestinationURL(destinationUIDRef, URL);

 

Thank you for your help.

 

/Karoly

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines